Files

1326 lines
60 KiB
C#
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
//FB 32926 Old location of this file is DataPRO\DataPRO\DataModel\Classes\TestTemplate\TestTemplateList.cs
using DTS.SensorDB;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DTS.Common.Base;
using DTS.Common.Enums;
using DTS.Common.Utilities.Logging;
using DTS.Common.ISO;
using DTS.Common.Storage;
using DTS.Slice.Users.UserSettings;
using DTS.Common.Enums.Sensors;
using DTS.Common.Events;
using Prism.Ioc;
using DTS.Common.Events.TestSetups.TestSetupsList;
using DTS.Common.Classes.Sensors;
using System.Threading.Tasks;
using DTS.Common.Interface.TestSetups.TestSetupsList;
using DTS.Common.SharedResource.Strings;
using DTS.Common.DataModel;
using DTS.Common.DataModel.Common;
using Prism.Events;
using System.Windows.Threading;
using System.Windows;
// ReSharper disable GenericEnumeratorNotDisposed
namespace DataPROWin7.DataModel
{
public class TestTemplateList : BasePropertyChanged
{
/// <summary>
/// this property is to hold a template in memory temporarily
/// without committing it to the db, but to still act as if it is in the db
/// </summary>
public TestTemplate TemporaryTemplate { get; set; }
protected TestTemplateList() { }
private IReadOnlyDictionary<string, CustomerDetails> _cachedCustomerDetails = null;
public IReadOnlyDictionary<string, CustomerDetails> CachedCustomerDetails
{
get => _cachedCustomerDetails;
set => _cachedCustomerDetails = value;
}
private IReadOnlyDictionary<string, LabratoryDetails> _cachedLaboratoryDetails = null;
public IReadOnlyDictionary<string, LabratoryDetails> CachedLaboratoryDetails
{
get => _cachedLaboratoryDetails;
set => _cachedLaboratoryDetails = value;
}
private IReadOnlyDictionary<string, TestEngineerDetails> _cachedTestEngineerDetails = null;
public IReadOnlyDictionary<string, TestEngineerDetails> CachedTestEngineerDetails
{
get => _cachedTestEngineerDetails;
set => _cachedTestEngineerDetails = value;
}
public enum Tags
{
TestTemplates,
CurrentTest,
SavedCurrentTest
}
public TestTemplate GetTemplate(string name, bool bLoad = true)
{
if (name == StringResources.QuickSensorCheck_DefaultTestName)
{
return TemporaryTemplate;
}
if (string.IsNullOrWhiteSpace(name)) { return null; }
TestTemplate[] templates = GetTemplates(name);
TestTemplate testTemplate = templates.Length > 0 ? templates[0] : null;
if (null != testTemplate && bLoad)
{
testTemplate.Load();
}
return testTemplate;
}
public TestTemplate[] GetTemplates(string[] names, bool bLoad = true)
{
var templates = new List<TestTemplate>();
foreach (string name in names)
{
var template = GetTemplate(name, bLoad);
if (null != template)
{
templates.Add(template);
}
}
return templates.ToArray();
}
/// <summary>
/// returns a lookup of customer detail name to customer detail
/// 28273 Calspan Centralized db performance needs to be improved
/// </summary>
/// <returns></returns>
private IReadOnlyDictionary<string, CustomerDetails> GetCustomerDetailsLookup()
{
var lookup = new Dictionary<string, CustomerDetails>();
try
{
var details = CustomerDetailsList.GetAllCustomers();
foreach (var detail in details) { lookup[detail.Name] = detail; }
}
catch (Exception ex) { APILogger.Log(ex); }
return lookup;
}
/// <summary>
/// returns a lookup of lab detail name to lab detail
/// 28273 Calspan Centralized db performance needs to be improved
/// </summary>
/// <returns></returns>
private IReadOnlyDictionary<string, LabratoryDetails> GetLabDetailsLookup()
{
var lookup = new Dictionary<string, LabratoryDetails>();
try
{
var details = LabratoryDetailsList.GetAllLabs();
foreach (var detail in details) { lookup[detail.Name] = detail; }
}
catch (Exception ex) { APILogger.Log(ex); }
return lookup;
}
private IReadOnlyDictionary<string, TestEngineerDetails> GetTestEngineerDetailsLookup()
{
var lookup = new Dictionary<string, TestEngineerDetails>();
try
{
var details = TestEngineerDetailsList.GetAllTestEngineers();
foreach (var detail in details) { lookup[detail.Name] = detail; }
}
catch (Exception ex) { APILogger.Log(ex); }
return lookup;
}
private TestTemplate[] GetTemplates(string name, TestSetupDefaults settings = null, bool bIgnoreUserTags = false)
{
if (null == settings)
{
settings = TestSetupDefaults.GetUserSettings(ApplicationProperties.CurrentUser.Id);
}
//fixes an error in cmdline import when servicelocator is null
IEventAggregator eventAggregator = null;
try
{
if (Application.Current.Dispatcher.CheckAccess())
{
eventAggregator = ContainerLocator.Container.Resolve<IEventAggregator>();
}
}
catch (Exception)
{
return new TestTemplate[0];
}
var testTemplates = new List<TestTemplate>(1000);
IReadOnlyDictionary<string, CustomerDetails> customerLookup = null;
if (RunTestVariables.InRunTest &&
CachedCustomerDetails != null &&
CachedCustomerDetails.Count() > 0)
{
customerLookup = CachedCustomerDetails;
}
else
{
customerLookup = GetCustomerDetailsLookup();
if (RunTestVariables.InRunTest)
{
CachedCustomerDetails = customerLookup;
}
else
{
CachedCustomerDetails = null;
}
}
IReadOnlyDictionary<string, LabratoryDetails> labLookup = null;
if (RunTestVariables.InRunTest &&
CachedLaboratoryDetails != null &&
CachedLaboratoryDetails.Count() > 0)
{
labLookup = CachedLaboratoryDetails;
}
else
{
labLookup = GetLabDetailsLookup();
if (RunTestVariables.InRunTest)
{
CachedLaboratoryDetails = labLookup;
}
else
{
CachedLaboratoryDetails = null;
}
}
IReadOnlyDictionary<string, TestEngineerDetails> testEngineerLookup = null;
if (RunTestVariables.InRunTest &&
CachedTestEngineerDetails != null &&
CachedTestEngineerDetails.Count() > 0)
{
testEngineerLookup = CachedTestEngineerDetails;
}
else
{
testEngineerLookup = GetTestEngineerDetailsLookup();
if (RunTestVariables.InRunTest)
{
CachedTestEngineerDetails = testEngineerLookup;
}
else
{
CachedTestEngineerDetails = null;
}
}
try
{
var hardware = TestTemplate.GetSimpleHardwares();
var hr = DbOperations.TestSetupsGet(null, name, settings.DefaultROIStart, settings.DefaultROIEnd,
settings.DefaultIgnoreShortedStart, settings.DefaultIgnoreShortedTrigger, out var records, out var errors);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
var tt = new TestTemplate(settings, false, hardware, record);
tt._bIsLoaded = false;
eventAggregator?.GetEvent<ProgressBarEvent>().Publish(new ProgressBarEventArg()
{ SetText = true, ProgressBarText = $"{StringResources.GettingTestSetup} {tt.Name}" });
if (customerLookup.ContainsKey(record.CustomerDetails)) { tt.CustomerDetails = customerLookup[record.CustomerDetails]; }
else { tt.CustomerDetails = CustomerDetailsList.GetCustomerDetail(record.CustomerDetails); }
if (testEngineerLookup.ContainsKey(record.TestEngineerDetails)) { tt.TestEngineerDetails = testEngineerLookup[record.TestEngineerDetails]; }
else { tt.TestEngineerDetails = TestEngineerDetailsList.TestEngineerList.GetTestEngineerDetail(record.TestEngineerDetails); }
tt.DownloadFolder = DataModelSettings.DownloadFolder;
tt.ExportFolder = DataModelSettings.DownloadFolder;
if (labLookup.ContainsKey(record.LabDetails)) { tt.LabDetails = labLookup[record.LabDetails]; }
else { tt.LabDetails = LabratoryDetailsList.GetLab(record.LabDetails); }
switch (ApplicationProperties.CurrentUser.Role)
{
case DTS.Slice.Users.User.DefaultRoles.Administrator:
break;
case DTS.Slice.Users.User.DefaultRoles.Guest:
case DTS.Slice.Users.User.DefaultRoles.PowerUser:
case DTS.Slice.Users.User.DefaultRoles.User:
if (!bIgnoreUserTags && !ApplicationProperties.CurrentUser.TagCompatible(tt.GetTagIDs()))
{
continue;
}
break;
}
if (string.IsNullOrEmpty(name) && tt.Name.Equals(DTS.Common.DataModel.Classes.TestTemplate.TSRAIRGoTestSetup.TEST_NAME))
{
//only return this template if we request it specifically ...
continue;
}
testTemplates.Add(tt);
}
}
if (null != eventAggregator && null != errors && errors.Any())
{
try
{
eventAggregator.GetEvent<PageErrorEvent>().Publish(new PageErrorArg(errors, null));
}
catch (Exception) { }
}
}
catch (Exception ex) { APILogger.Log("failed to retrieve test templates", ex); }
eventAggregator?.GetEvent<ProgressBarEvent>().Publish(new ProgressBarEventArg()
{ SetText = true, ProgressBarText = string.Empty });
return testTemplates.ToArray();
}
private async Task<TestTemplate[]> GetTemplatesAync(string name, TestSetupDefaults settings = null, bool bIgnoreUserTags = false)
{
//fixes an error in cmdline import when servicelocator is null
IEventAggregator eventAggregator = null;
try
{
if (Application.Current.Dispatcher.CheckAccess())
{
eventAggregator = ContainerLocator.Container.Resolve<IEventAggregator>();
}
}
catch (Exception)
{
return new TestTemplate[0];
}
var testTemplates = new List<TestTemplate>(100);
try
{
var hardware = TestTemplate.GetSimpleHardwares();
if (null == settings) { settings = TestSetupDefaults.GetUserSettings(ApplicationProperties.CurrentView.Id); }
var hr = DbOperations.TestSetupsGet(null, name, settings.DefaultROIStart, settings.DefaultROIEnd,
settings.DefaultIgnoreShortedStart, settings.DefaultIgnoreShortedTrigger, out var records, out var errors);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
var tt = new TestTemplate(settings, false, hardware, record);
eventAggregator?.GetEvent<ProgressBarEvent>().Publish(new ProgressBarEventArg()
{ SetText = true, ProgressBarText = $"{StringResources.GettingTestSetup} {tt.Name}" });
tt.CustomerDetails = CustomerDetailsList.GetCustomerDetail(record.CustomerDetails);
tt.TestEngineerDetails = TestEngineerDetailsList.TestEngineerList.GetTestEngineerDetail(record.TestEngineerDetails);
tt.DownloadFolder = DataModelSettings.DownloadFolder;
tt.ExportFolder = DataModelSettings.DownloadFolder;
tt.LabDetails = LabratoryDetailsList.GetLab(record.LabDetails);
switch (ApplicationProperties.CurrentUser.Role)
{
case DTS.Slice.Users.User.DefaultRoles.Administrator:
break;
case DTS.Slice.Users.User.DefaultRoles.Guest:
case DTS.Slice.Users.User.DefaultRoles.PowerUser:
case DTS.Slice.Users.User.DefaultRoles.User:
if (!bIgnoreUserTags && !ApplicationProperties.CurrentUser.TagCompatible(tt.GetTagIDs()))
{
continue;
}
break;
}
testTemplates.Add(tt);
}
}
if (null != eventAggregator && null != errors && errors.Any())
{
try
{
eventAggregator.GetEvent<PageErrorEvent>().Publish(new PageErrorArg(errors, null));
}
catch (Exception) { }
}
}
catch (Exception ex) { APILogger.Log("failed to retrieve test templates", ex); }
eventAggregator?.GetEvent<ProgressBarEvent>().Publish(new ProgressBarEventArg()
{ SetText = true, ProgressBarText = string.Empty });
return testTemplates.ToArray();
}
private void Commit(TestTemplate template, string user, bool bNotify, bool bUpdateTestSetupList = true)
{
TestSetupUpdate(user, template, bNotify);
template.MarkIsCompleteUnchecked();
}
/// <summary>
/// FB 15880 Delete multiple tests
/// </summary>
/// <param name="testSetupIds">the list of the tests which should be deleted</param>
/// <param name="updateTestSetupList"></param>
private void DeleteMultipleTestSetups(List<int> testSetupIds, bool updateTestSetupList = true)
{
if (!testSetupIds.Any()) { return; }
testSetupIds.Sort();
_ = DbOperations.TestSetupsDeleteById(testSetupIds.ToArray());
/// 15877 deleting multiple test setups takes too much time.
/// 15880 it should not take much time to delete multiple test setups , we can always pass true now
if (updateTestSetupList)
{
TestSetupCollection.UpdateTestSetupList();
OnPropertyChanged(Tags.TestTemplates.ToString());
}
}
/// <summary>
/// FB 15880 Delete multiple tests
/// </summary>
/// <param name="testSetupNames">the list of the tests which should be deleted</param>
/// <param name="updateTestSetupList"></param>
private void DeleteMultipleTestSetups(List<string> testSetupNames, bool updateTestSetupList = true)
{
if (!testSetupNames.Any()) { return; }
testSetupNames.Sort();
_ = DbOperations.TestSetupsDeleteByName(testSetupNames.ToArray());
/// 15877 deleting multiple test setups takes too much time.
/// 15880 it should not take much time to delete multiple test setups , we can always pass true now
if (updateTestSetupList)
{
TestSetupCollection.UpdateTestSetupList();
OnPropertyChanged(Tags.TestTemplates.ToString());
}
}
/// <summary>
/// this function directly updates the template name in the database
/// this was done during testing of 13563 Copy a test, save (get warning about name). Change the name and save, but get same warning the next time I make a change
/// I noticed that renaming a test setup was no longer resulting in a delete and an insert but
/// inserting a new test and pointing it to the objects used by the old one
/// I'm not sure when this broke, but a solution to this is update the template name in the database, this way you'll be updating
/// the existing test setup rather than creating a new one.
/// </summary>
/// <param name="template"></param>
private void UpdateTemplateNameIfNeeded(TestTemplate template)
{
//it was creating new test setups when you renamed a test setup. this is unintentional and changed at some point in the past
//to fix this, if we have a positive id we have to update the name first
//however we need to make sure the name doesn't already belong to a different test setup
if (template.Id > 0)
{
bool bFound = false;
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.Text;
sql.CommandText = "SELECT [TestSetupId] FROM [TestSetups] WHERE [TestSetupName]=@1";
sql.Parameters.Add(new SqlParameter("@1", SqlDbType.NVarChar) { Value = template.Name });
using (var reader = sql.ExecuteReader())
{
while (reader.Read())
{
var id = Convert.ToInt32(reader["TestSetupId"]);
if (id != template.Id)
{
throw new Exception("Test setup name already belongs to a different test setup");
}
bFound = true;
}
}
}
finally
{
sql.Connection.Dispose();
}
}
if (!bFound)
{
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.Text;
sql.CommandText = "UPDATE [TestSetups] SET [TestSetupName]=@1 WHERE [TestSetupId]=@2";
sql.Parameters.Add(new SqlParameter("@1", SqlDbType.NVarChar, 255) { Value = template.Name });
sql.Parameters.Add(new SqlParameter("@2", SqlDbType.BigInt) { Value = template.Id });
sql.ExecuteNonQuery();
}
finally
{
sql.Connection.Dispose();
}
}
}
}
}
/// <summary>
/// Update or insert Test Setup and related records
/// </summary>
/// <param name="user"></param>
/// <param name="template"></param>
/// <param name="bNotify"></param>
public void TestSetupUpdate(string user, TestTemplate template, bool bNotify)
{
var testSetupId = 0;
UpdateTemplateNameIfNeeded(template);
#region Insert into TestSetups table
template.LastModified = DateTime.Now;
template.LastModifiedBy = user;
template.IsDirty = false;
var record = (ITestSetupRecord)template;
if (null != template.CustomerDetails)
{
record.CustomerDetails = template.CustomerDetails.Name;
}
if (null != template.TestEngineerDetails)
{
record.TestEngineerDetails = template.TestEngineerDetails.Name;
}
if (null != template.LabDetails)
{
record.LabDetails = template.LabDetails.Name;
}
record.AlignUDPToPPS = template.AlignUDPToPPS;
template.Settings = template.GetSettings();
var hr = DbOperations.TestSetupsUpdateInsert(ref record);
if (0 != hr)
{
APILogger.Log($"TestSetupUpdate failed: {hr}");
return;
}
testSetupId = record.Id;
#endregion Test Setups Table
template.SaveHardware();
template.SetTestSetupChannelOrder();
//25620 Exception thrown when TSR AIR with a level trigger is removed from a Test Setup
//SaveGroups can cause channels to be deleted, but level trigger has a constraint on channel id
//so those have to be removed before channels are saved
//note that level triggers were ordinarily deleted and inserted as needed later on
DeleteLevelTriggers(template.Name);
template.SaveGroups();
#region Graphs table
//14796 Cannot remove graph from test setup
//ALWAYS update graphs, there may be existing graphs we need to remove
template.Id = testSetupId;
UpdateGraphs(template);
#endregion Graphs table
UpdateCalculatedChannels(testSetupId, template);
#region Insert object meta data
DeleteTestObjectMetaData(testSetupId, template.Name);
UpdateTestObjectMetaData(testSetupId, template);
#endregion Meta data
#region Test meta data
//DeleteTestMetaData(testSetupId, template.Name);
var testMetaData = UpdateTestMetaData(testSetupId, template);
#endregion Test meta data
#region Insert Level Triggers
UpdateLevelTriggers(testSetupId, template);
#endregion LevelTriggers
#region UpdateROIs
var dbVersion = DbOperations.GetConnectionDbVersion();
if (dbVersion >= DTS.Common.Constants.ROITables_DB_VERSION)
{
UpdateROIs(testSetupId, template);
}
#endregion UpdateROIs
}
#region TestSetupUpdate related functions
private void UpdateROIs(int testSetupId, TestTemplate template)
{
var hresult = DbOperations.RegionsOfInterestDelete(testSetupId);
foreach (var regionOfInterest in template.RegionsOfInterest)
{
hresult = DbOperations.RegionsOfInterestInsert(testSetupId, regionOfInterest);
}
}
private void DeleteLevelTriggers(string testSetupName)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_LevelTriggersDelete.ToString();
#region params
cmd.Parameters.Add(
new SqlParameter("@TestSetupName", SqlDbType.NVarChar, 255) { Value = testSetupName });
cmd.Parameters.Add(
new SqlParameter("@Id", SqlDbType.Int) { Value = DBNull.Value });
cmd.Parameters.Add(
new SqlParameter("@ChannelId", SqlDbType.Int) { Value = DBNull.Value });
cmd.Parameters.Add(
new SqlParameter("@TestSetupId", SqlDbType.Int) { Value = DBNull.Value });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
APILogger.Log(errorMessageParam.Value.ToString());
}
}
finally { cmd.Connection.Dispose(); }
}
}
/// <summary>
/// Update Level Triggers
/// </summary>
/// <param name="testSetupId"></param>
/// <param name="template"></param>
private void UpdateLevelTriggers(int testSetupId, TestTemplate template)
{
//eliminate any invalid level triggers
template.RemoveImpossibleLevelTriggers();
DeleteLevelTriggers(template.Name);
try
{
if (template.LevelTriggerChannels.Count <= 0) return;
var e = template.LevelTriggerChannels.GetEnumerator();
while (e.MoveNext())
{
var lt = e.Current.Value;
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_LevelTriggersInsert.ToString();
#region params
cmd.Parameters.Add(
new SqlParameter("@TestSetupId", SqlDbType.Int) { Value = DBNull.Value });
cmd.Parameters.Add(
new SqlParameter("@TestSetupName", SqlDbType.NVarChar, 255) { Value = template.Name });
cmd.Parameters.Add(
new SqlParameter("@ChannelId", SqlDbType.BigInt) { Value = lt.GroupChannel.Id });
//cmd.Parameters.Add(
// new SqlParameter("@GroupSerialNumber", SqlDbType.NVarChar, 255)
// {
// Value = lt.GroupSerialNumber
// });
//cmd.Parameters.Add(
// new SqlParameter("@TestObjectChannelId", SqlDbType.NVarChar, 255)
// {
// Value = lt.TestObjectChannelId
// });
//cmd.Parameters.Add(
// new SqlParameter("@HardwareChannelId", SqlDbType.NVarChar, 255)
// {
// Value = lt.HardwareChannelId
// });
//cmd.Parameters.Add(
// new SqlParameter("@SensorSerialNumber", SqlDbType.NVarChar, 255)
// {
// Value = lt.SensorSerialNumber
// }); /* TODO: remove later*/
cmd.Parameters.Add(
new SqlParameter("@GreaterThanEnabled", SqlDbType.Bit) { Value = lt.GreaterThanEnabled });
cmd.Parameters.Add(
new SqlParameter("@GreaterThanEU", SqlDbType.Float)
{
Value = lt.GreaterThanThresholdEU
});
cmd.Parameters.Add(
new SqlParameter("@LessThanEnabled", SqlDbType.Bit) { Value = lt.LessThanEnabled });
cmd.Parameters.Add(
new SqlParameter("@LessThanEU", SqlDbType.Float) { Value = lt.LessThanThresholdEU });
cmd.Parameters.Add(
new SqlParameter("@InsideUpperEU", SqlDbType.Float) { Value = lt.InsideUpperLevelEU });
cmd.Parameters.Add(
new SqlParameter("@InsideLowerEU", SqlDbType.Float) { Value = lt.InsideLowerLevelEU });
cmd.Parameters.Add(
new SqlParameter("@OutsideUpperEU", SqlDbType.Float) { Value = lt.OutsideUpperLevelEU });
cmd.Parameters.Add(
new SqlParameter("@OutsideLowerEU", SqlDbType.Float) { Value = lt.OutsideLowerLevelEU });
cmd.Parameters.Add(
new SqlParameter("@InsideEnabled", SqlDbType.Bit) { Value = lt.TriggerBetweenBounds });
cmd.Parameters.Add(
new SqlParameter("@OutsideEnabled", SqlDbType.Bit) { Value = lt.TriggerOutsideBounds });
//cmd.Parameters.Add(
// new SqlParameter("@TriggerInside", SqlDbType.Bit) { Value = lt.TriggerBetweenBounds });
//cmd.Parameters.Add(
// new SqlParameter("@TriggerOutside", SqlDbType.Bit) { Value = lt.TriggerOutsideBounds });
var newIdParam =
new SqlParameter("@new_id", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(newIdParam);
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
APILogger.Log(errorMessageParam.Value.ToString());
}
}
finally { cmd.Connection.Dispose(); }
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
//throw new Exception("");
}
/// <summary>
/// Update Test Setup Calculated Channels
/// </summary>
/// <param name="testSetupId"></param>
/// <param name="template"></param>
private void UpdateCalculatedChannels(int testSetupId, TestTemplate template)
{
//remap the -1 in input channel id for any input channels which were new (but are now in the db and have a valid id)
template.UpdateCalculatedChannelInputIds();
//step 1, get all existing calcualted channels
var presentIds = new HashSet<int>();
foreach (var cc in template.CalculatedChannels)
{
if (cc.Id > 0)
{
presentIds.Add(cc.Id);
}
}
var existingCalculatedChannelIds = GetExistingCalculatedChannelIds(template.Name);
//step 2, remove no longer needed channels
var toRemove = new List<int>();
foreach (var id in existingCalculatedChannelIds)
{
if (!presentIds.Contains(id))
{
toRemove.Add(id);
}
}
foreach (var id in toRemove)
{
DeleteCalculatedChannel(id);
}
//step 3, update existing channels
foreach (var cc in template.CalculatedChannels)
{
if (cc.Id > 0)
{
//if the Calculated channel has an id, but that's not an id in the db for the test, well
//updating it won't work, insert it instead
if (!existingCalculatedChannelIds.Contains(cc.Id)) { cc.Id = -1; }
else { UpdateCalculatedChannel(cc, template.Name); }
}
}
//step 4, add new calculated channels
foreach (var cc in template.CalculatedChannels)
{
if (cc.Id <= 0)
{
InsertCalculatedChannel(cc, template.Name);
}
}
}
private void InsertCalculatedChannel(CalculatedValueClass cc, string testSetupName)
{
cc.TestSetupName = testSetupName;
_ = DbOperations.CalculatedChannelsInsert(cc);
}
private void UpdateCalculatedChannel(CalculatedValueClass cc, string testSetupName)
{
cc.TestSetupName = testSetupName;
_ = DbOperations.CalculatedChannelsUpdate(cc);
}
private void DeleteCalculatedChannel(int id)
{
_ = DbOperations.CalculatedChannelsDelete(id);
}
private int[] GetExistingCalculatedChannelIds(string testName)
{
var list = new List<int>();
var hr = DbOperations.CalculatedChannelsGet(null, testName, out var records);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
if (!list.Contains(record.Id))
{
list.Add(record.Id);
}
}
}
return list.ToArray();
}
/// <summary>
/// Update Test Meta Data
/// </summary>
/// <param name="testSetupId"></param>
/// <param name="template"></param>
/// <returns></returns>
private TestSetupMetaData UpdateTestMetaData(int testSetupId, TestTemplate template)
{
var testMeta = template.GetTestMetaData();
// FB 17951 Prevent empty TestObject entry
if (string.IsNullOrWhiteSpace(testMeta.TestObject.ToString()))
{
return testMeta;
}
foreach (var prop in testMeta.Properties)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TestSetupObjectMetaDataInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@TestSetupId", SqlDbType.Int) { Value = testSetupId });
cmd.Parameters.Add(
new SqlParameter("@TestSetupName", SqlDbType.NVarChar, 50) { Value = template.Name });
cmd.Parameters.Add(
new SqlParameter("@ISOTestObject", SqlDbType.NVarChar, 1) { Value = testMeta.TestObject });
cmd.Parameters.Add(new SqlParameter("@PropName", SqlDbType.NVarChar, 255) { Value = prop.Name });
cmd.Parameters.Add(
new SqlParameter("@PropValue", SqlDbType.NVarChar, 255) { Value = prop.Value ?? "" });
cmd.Parameters.Add(new SqlParameter("@Optional", SqlDbType.Bit) { Value = prop.IsOptional });
cmd.Parameters.Add(new SqlParameter("@Version", SqlDbType.Float) { Value = prop.Version });
var newIdParam =
new SqlParameter("@new_id", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(newIdParam);
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
APILogger.Log(errorMessageParam.Value.ToString());
}
}
finally { cmd.Connection.Dispose(); }
}
}
return testMeta;
}
private void DeleteTestObjectMetaData(int testSetupId, string testSetupName)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TestSetupObjectMetaDataDelete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@TestSetupId", SqlDbType.Int) { Value = testSetupId });
cmd.Parameters.Add(
new SqlParameter("@TestSetupName", SqlDbType.NVarChar, 50) { Value = testSetupName });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
APILogger.Log(errorMessageParam.Value.ToString());
}
}
finally { cmd.Connection.Dispose(); }
}
}
/// <summary>
/// Update Test Object Meta Data
/// </summary>
/// <param name="testSetupId"></param>
/// <param name="template"></param>
private void UpdateTestObjectMetaData(int testSetupId, TestTemplate template)
{
foreach (var metadata in template.GetMetaData())
{
// FB 17951 Prevent empty TestObject entry
if (string.IsNullOrWhiteSpace(metadata.TestObject.ToString()))
{
continue;
}
foreach (var prop in metadata.Properties)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText =
DbOperationsEnum.StoredProcedure.sp_TestSetupObjectMetaDataInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@TestSetupId", SqlDbType.Int) { Value = testSetupId });
cmd.Parameters.Add(
new SqlParameter("@TestSetupName", SqlDbType.NVarChar, 50) { Value = template.Name });
cmd.Parameters.Add(
new SqlParameter("@ISOTestObject", SqlDbType.NVarChar, 1)
{
Value = metadata.TestObject
});
cmd.Parameters.Add(
new SqlParameter("@PropName", SqlDbType.NVarChar, 255) { Value = prop.Name });
cmd.Parameters.Add(
new SqlParameter("@PropValue", SqlDbType.NVarChar, 255) { Value = prop.Value });
cmd.Parameters.Add(new SqlParameter("@Optional", SqlDbType.Bit) { Value = prop.IsOptional });
cmd.Parameters.Add(new SqlParameter("@Version", SqlDbType.Float) { Value = prop.Version });
var newIdParam =
new SqlParameter("@new_id", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(newIdParam);
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
APILogger.Log(errorMessageParam.Value.ToString());
}
}
finally { cmd.Connection.Dispose(); }
}
}
}
}
private void UpdateGraphs(TestTemplate test)
{
//1, get list of existing graphs for test setup
var existingIds = GetExistingGraphIds(test.Id);
//2, delete any graphs no longer needed
var existing = new HashSet<int>();
foreach (var graph in test.TestGraphs)
{
existing.Add(graph.GraphId);
}
var toDelete = new List<int>();
foreach (var id in existingIds)
{
if (!existing.Contains(id))
{
toDelete.Add(id);
}
}
foreach (var id in toDelete)
{
DeleteGraph(id);
}
//3, update
foreach (var graph in test.TestGraphs)
{
if (graph.GraphId > 0)
{
graph.TestSetupId = test.Id;
UpdateGraph(graph);
}
}
//4, add any new ones
foreach (var graph in test.TestGraphs)
{
if (graph.GraphId <= 0)
{
graph.TestSetupId = test.Id;
InsertGraph(graph);
}
}
}
private void UpdateGraph(TestGraph graph)
{
graph.UpdateChannelAndThresholdStrings();
_ = DbOperations.TestGraphsUpdate(graph);
}
private void InsertGraph(TestGraph graph)
{
graph.UpdateChannelAndThresholdStrings();
_ = DbOperations.TestGraphsInsert(graph);
}
private void DeleteGraph(int id)
{
_ = DbOperations.TestGraphsDelete(id);
}
private int[] GetExistingGraphIds(int testSetupId)
{
var list = new List<int>();
var hr = DbOperations.TestGraphsGet(null, testSetupId, out var records);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
list.Add(record.GraphId);
}
}
return list.ToArray();
}
#endregion TestSetupUpdate related functions
public static SensorData GetSensorFromSettings(string settings, string serial, Dictionary<string, SensorData> lookup)
{
SensorData sd = null;
if (null != lookup && lookup.ContainsKey(serial)) { sd = lookup[serial]; }
if (null == sd) { sd = SensorsCollection.SensorsList.GetSensorBySerialNumber(serial); }
if (string.IsNullOrWhiteSpace(serial))
{
sd = new SensorData { SerialNumber = "" };
}
if (null == sd) { return null; }
sd = new SensorData(sd);
var tokens = settings.Split(',');
foreach (var token in tokens)
{
var subtokens = token.Split('=');
var setting = (SensorConstants.SensorSettings)int.Parse(subtokens[0]);
switch (setting)
{
case SensorConstants.SensorSettings.CFC:
sd.FilterClassIso = subtokens[1];
break;
//FB 13120 filter class setting;
case SensorConstants.SensorSettings.FilterClass:
sd.FilterClass = FilterClass.GetFilterClassFromFilterClassSetting(subtokens[1]);
break;
case SensorConstants.SensorSettings.Position:
sd.Position = subtokens[1];
break;
case SensorConstants.SensorSettings.Polarity:
sd.Invert = subtokens[1] == "-";
break;
case SensorConstants.SensorSettings.Range:
sd.Capacity = double.Parse(subtokens[1], System.Globalization.CultureInfo.InvariantCulture);
break;
case SensorConstants.SensorSettings.Delay:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.DelayMS = double.Parse(subtokens[1], System.Globalization.CultureInfo.InvariantCulture); sd.DigitalOutputDelayMS = sd.DelayMS; }
break;
case SensorConstants.SensorSettings.Duration:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.DurationMS = double.Parse(subtokens[1], System.Globalization.CultureInfo.InvariantCulture); sd.DigitalOutputDurationMS = sd.DurationMS; }
break;
case SensorConstants.SensorSettings.OutputMode:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.DigitalOutputMode = (DigitalOutputModes)Convert.ToInt32(subtokens[1]); }
break;
case SensorConstants.SensorSettings.SQMode:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.SquibFireMode = (SquibFireMode)Convert.ToInt32(subtokens[1]); }
break;
case SensorConstants.SensorSettings.DIMode:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.InputMode = (DigitalInputModes)Convert.ToInt32(subtokens[1]); }
break;
case SensorConstants.SensorSettings.LimitDuration:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.LimitDuration = bool.Parse(subtokens[1]); }
break;
case SensorConstants.SensorSettings.ActiveValue:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.ScaleMultiplier.ActiveValue = Convert.ToDouble(subtokens[1]); }
break;
case SensorConstants.SensorSettings.DefaultValue:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.ScaleMultiplier.DefaultValue = Convert.ToDouble(subtokens[1]); }
break;
case SensorConstants.SensorSettings.DigitalOutDelay:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.DigitalOutputDelayMS = Convert.ToDouble(subtokens[1], System.Globalization.CultureInfo.InvariantCulture); }
break;
case SensorConstants.SensorSettings.DigitalOutDuration:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.DigitalOutputDurationMS = Convert.ToDouble(subtokens[1], System.Globalization.CultureInfo.InvariantCulture); }
break;
case SensorConstants.SensorSettings.DigitalOutLimitDuration:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.DigitalOutputLimitDuration = Convert.ToBoolean(subtokens[1]); }
break;
case SensorConstants.SensorSettings.SquibDelay:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.SquibFireDelayMS = Convert.ToDouble(subtokens[1], System.Globalization.CultureInfo.InvariantCulture); }
break;
case SensorConstants.SensorSettings.SquibDuration:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.SquibFireDurationMS = Convert.ToDouble(subtokens[1], System.Globalization.CultureInfo.InvariantCulture); }
break;
case SensorConstants.SensorSettings.SquibLimitDuration:
if (!string.IsNullOrWhiteSpace(subtokens[1])) { sd.LimitSquibFireDuration = Convert.ToBoolean(subtokens[1]); }
break;
}
}
return sd;
}
public static SensorData GetSensorFromSettings(string settings, string serial)
{
return GetSensorFromSettings(settings, serial, null);
}
public static string GetSensorSettings(SensorData sd)
{
var list = new List<string>();
switch (sd.Bridge)
{
case SensorConstants.BridgeType.RTC:
case SensorConstants.BridgeType.IEPE:
case SensorConstants.BridgeType.QuarterBridge:
case SensorConstants.BridgeType.HalfBridge:
case SensorConstants.BridgeType.FullBridge:
case SensorConstants.BridgeType.HalfBridge_SigPlus:
list.Add($"{(int)SensorConstants.SensorSettings.CFC}={sd.FilterClassIso}");
//FB 13120 filter class setting
list.Add($"{(int)SensorConstants.SensorSettings.FilterClass}={$"{sd.FilterClass.FClass},{sd.FilterClass.Frequency}"}");
list.Add($"{(int)SensorConstants.SensorSettings.Polarity}={(sd.Invert ? "-" : "+")}");
list.Add($"{(int)SensorConstants.SensorSettings.Position}={sd.Position}");
list.Add($"{(int)SensorConstants.SensorSettings.Range}={sd.Capacity.ToString(System.Globalization.CultureInfo.InvariantCulture)}");
break;
case SensorConstants.BridgeType.DigitalInput:
list.Add($"{(int)SensorConstants.SensorSettings.DIMode}={(int)sd.InputMode}");
list.Add($"{(int)SensorConstants.SensorSettings.ActiveValue}={sd.ScaleMultiplier.ActiveValue.ToString(System.Globalization.CultureInfo.InvariantCulture)}");
list.Add($"{(int)SensorConstants.SensorSettings.DefaultValue}={sd.ScaleMultiplier.DefaultValue.ToString(System.Globalization.CultureInfo.InvariantCulture)}");
break;
case SensorConstants.BridgeType.SQUIB:
list.Add($"{(int)SensorConstants.SensorSettings.SQMode}={(int)sd.SquibFireMode}");
list.Add($"{(int)SensorConstants.SensorSettings.SquibDelay}={sd.SquibFireDelayMS.ToString(System.Globalization.CultureInfo.InvariantCulture)}");
list.Add($"{(int)SensorConstants.SensorSettings.SquibDuration}={sd.SquibFireDurationMS.ToString(System.Globalization.CultureInfo.InvariantCulture)}");
list.Add($"{(int)SensorConstants.SensorSettings.SquibLimitDuration}={sd.LimitSquibFireDuration.ToString()}");
break;
case SensorConstants.BridgeType.TOMDigital:
list.Add($"{(int)SensorConstants.SensorSettings.OutputMode}={(int)sd.DigitalOutputMode}");
list.Add($"{(int)SensorConstants.SensorSettings.DigitalOutDelay}={sd.DigitalOutputDelayMS.ToString(System.Globalization.CultureInfo.InvariantCulture)}");
list.Add($"{(int)SensorConstants.SensorSettings.DigitalOutDuration}={sd.DigitalOutputDurationMS.ToString(System.Globalization.CultureInfo.InvariantCulture)}");
list.Add($"{(int)SensorConstants.SensorSettings.DigitalOutLimitDuration}={sd.DigitalOutputLimitDuration.ToString()}");
break;
}
return string.Join(",", list.ToArray());
}
public void CommitGroupOfTemplates(TestTemplate[] templates, bool bNotify)
{
foreach (var template in templates)
{
Commit(template, ApplicationProperties.CurrentUser.UserName, bNotify, false);
template.MarkIsCompleteUnchecked();
}
if (1 == templates.Length)
{
TestSetupCollection.UpdateTestSetupList(templates.FirstOrDefault());
}
else { TestSetupCollection.UpdateTestSetupList(); }
OnPropertyChanged(Tags.TestTemplates.ToString());
}
public void Commit(TestTemplate template) { Commit(template, true); }
public void Commit(TestTemplate template, bool bNotify)
{
CommitGroupOfTemplates(new[] { template }, bNotify);
}
private TestTemplate _currentTest;
public TestTemplate CurrentTest
{
get => _currentTest;
set
{
SetProperty(ref _currentTest, value, Tags.CurrentTest.ToString());
//FB14483 "Should not include calculated channel when running test if Calculated Channel UI is not enabled either"
if (!Common.SerializedSettings.AllowCalculatedChannels) CurrentTest?.CalculatedChannels.Clear();
var eventAggregator = ContainerLocator.Container.Resolve<IEventAggregator>();
eventAggregator.GetEvent<CurrentTestChangedEvent>().Publish(value?.Name ?? string.Empty);
}
}
private TestTemplate _savedCurrentTest;
public TestTemplate SavedCurrentTest
{
get => _savedCurrentTest;
set => SetProperty(ref _savedCurrentTest, value, Tags.SavedCurrentTest.ToString());
}
private static TestTemplateList _list;
private static readonly object ObjectLock = new object();
public static TestTemplateList TestTemplatesList
{
get
{
lock (ObjectLock)
{
if (null == _list) { _list = new TestTemplateList(); }
}
return _list;
}
}
/// <summary>
/// delete templates from the db and remove them from the list of templates
/// </summary>
/// <param name="testSetupIds">test id of templates to delete</param>
/// <param name="user"></param>
public void DeleteTestSetups(List<int> testSetupIds, string user)
{
DeleteMultipleTestSetups(testSetupIds);
OnPropertyChanged(Tags.TestTemplates.ToString());
}
/// <summary>
/// delete templates from the db and remove them from the list of templates
/// </summary>
/// <param name="testSetupIds">test id of templates to delete</param>
/// <param name="user"></param>
public void DeleteTestSetups(List<string> testSetupNames, string user)
{
DeleteMultipleTestSetups(testSetupNames);
OnPropertyChanged(Tags.TestTemplates.ToString());
}
public TestTemplate[] TestTemplates
{
get
{
var templates = new List<TestTemplate>(GetAllTemplates());
for (var i = templates.Count - 1; i >= 0; i--)
{
if (!templates[i].IsComplete) { templates.RemoveAt(i); }
}
templates.Sort();
return templates.ToArray();
}
}
public TestTemplate[] AllTemplates
{
get
{
var templates = new List<TestTemplate>(GetAllTemplates());
templates.Sort();
return templates.ToArray();
}
}
public async Task<TestTemplate[]> GetAllTemplatesAync()
{
var unsortedTemplates = await GetAllTemplatesForUserAsync(false);
var templates = new List<TestTemplate>(unsortedTemplates);
templates.Sort();
return templates.ToArray();
}
private TestTemplate[] GetAllTemplates()
{
return GetAllTemplatesForUser(false);
}
public TestTemplate[] GetAllTemplatesForUser(bool bIgnoreUserTags = false)
{
var settings = TestSetupDefaults.GetUserSettings(ApplicationProperties.CurrentUser.Id);
return GetTemplates(null, settings, bIgnoreUserTags);
}
public async Task<TestTemplate[]> GetAllTemplatesForUserAsync(bool bIgnoreUserTags = false)
{
var settings = TestSetupDefaults.GetUserSettings(ApplicationProperties.CurrentUser.Id);
return await GetTemplatesAync(null, settings, bIgnoreUserTags);
}
public static void ConvertToDictionary(IDataReader reader, ref Dictionary<string, List<Dictionary<string, object>>> lookup, string key)
{
var count = reader.FieldCount;
var names = new string[count];
for (var i = 0; i < names.Length; i++)
{
names[i] = reader.GetName(i);
}
while (reader.Read())
{
var thiskey = Convert.ToString(reader[key]);
if (!lookup.ContainsKey(thiskey)) { lookup.Add(thiskey, new List<Dictionary<string, object>>()); }
var properties = new Dictionary<string, object>(count);
foreach (var column in names)
{
properties[column] = reader[column];
}
lookup[thiskey].Add(properties);
}
}
}
}