Files
DP44/DataPRO/SensorDB/SensorsCollection.cs
2026-04-17 14:55:32 -04:00

1589 lines
58 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DTS.Common.Enums;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.Channels.ChannelCodes;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
using Prism.Ioc;
using Prism.Events;
using Unity;
using DTS.Common;
namespace DTS.SensorDB
{
public class SensorsCollection : INotifyPropertyChanged
{
/// <summary>
/// these are sensors unmodified from a cache
/// </summary>
private SensorData[] _originalCachedSensors = new SensorData[0];
/// <summary>
/// these are sensors modified from a cache (channel settings applied)
/// </summary>
private SensorData[] _cachedSensors = new SensorData[0];
public SensorData[] CachedSensors
{
get => _cachedSensors;
set => _cachedSensors = value;
}
public void ClearCache()
{
_cachedSensors = new SensorData[0];
_originalCachedSensors = new SensorData[0];
}
/// <summary>
/// sets the cache of current sensors
/// to be used when GetSensor is called with UseCache as true
/// </summary>
/// <param name="cachedSensors">sensors to cache (with channel settings already applied)</param>
/// <param name="originalCachedSensors">sensors cached unadulterated (to show differences in the UI, etc)</param>
public void SetCache(SensorData[] cachedSensors, SensorData[] originalCachedSensors)
{
_cachedSensors = cachedSensors;
_originalCachedSensors = originalCachedSensors;
}
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, String propertyName = null)
{
if (Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
private volatile bool _hookedup = true;
public bool HookedUp
{
get => _hookedup;
set
{
_hookedup = value;
OnPropertyChanged("AllSensors");
}
}
protected void OnPropertyChanged(string propertyName = null)
{
if (!HookedUp)
{
return;
}
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private static readonly object _lock = new object();
public void Reload()
{
//lock (_lock)
//{
// _sensorCollection.LoadAllSensors();
//}
}
private static SensorsCollection _sensorCollection;
public static SensorsCollection SensorsList
{
get
{
lock (_lock)
{
return _sensorCollection ?? (_sensorCollection = new SensorsCollection());
}
}
}
public void Notify()
{
OnPropertyChanged("AllSensors");
}
private enum SensorDataType
{
Analog = 0x00,
DigitalInput = 0x01,
DigitalOutput = 0x02,
Squib = 0x04
}
//TODO: IsSensorInUse
public string IsSensorInUse(SensorData sd)
{
var rv = string.Empty;
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_SensorInUse.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@Id", SqlDbType.Int) { Value = null });
cmd.Parameters.Add(new SqlParameter("@SerialNumber", SqlDbType.NVarChar, 50) { Value = sd.SerialNumber });
short sensorType = 0;
if (sd.IsDigitalInput())
{
sensorType = 1;
}
else if (sd.IsDigitalOutput())
{
sensorType = 2;
}
else if (sd.IsSquib())
{
sensorType = 3;
}
cmd.Parameters.Add(new SqlParameter("@SensorType", SqlDbType.TinyInt) { Value = sensorType });
#endregion
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables.Count <= 0 || ds.Tables[0].Rows.Count <= 0) return rv;
rv = ds.Tables[0].Rows.Cast<DataRow>().Aggregate(rv,
(current, dr) => current + Environment.NewLine + dr[0].ToString());
}
}
finally
{
cmd.Connection.Dispose();
}
}
return rv;
}
#region Remove orphan records
public void DeleteTestObjectSensors(string sensorId)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TestObjectSensorsDelete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@TestObjectId", SqlDbType.Int) { Value = 0 });
cmd.Parameters.Add(new SqlParameter("@TestObjectName", SqlDbType.NVarChar, 255) { Value = null });
cmd.Parameters.Add(
new SqlParameter("@SensorSerialNumber", SqlDbType.NVarChar, 50) { Value = sensorId });
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)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
public void DeleteTestObjectChannelSettings(string sensorId)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TestObjectChannelSettingsDelete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@TestObjectId", SqlDbType.Int) { Value = 0 });
cmd.Parameters.Add(new SqlParameter("@TestObjectName", SqlDbType.NVarChar, 255) { Value = null });
cmd.Parameters.Add(
new SqlParameter("@SensorSerialNumber", SqlDbType.NVarChar, 50) { Value = sensorId });
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)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
public void DeleteTestChannelSettings(string sensorId)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TestChannelSettingsDelete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@TestSetupId", SqlDbType.Int) { Value = 0 });
cmd.Parameters.Add(new SqlParameter("@TestSetupName", SqlDbType.NVarChar, 255) { Value = null });
cmd.Parameters.Add(new SqlParameter("@SensorId", SqlDbType.Int) { Value = 0 }); //TODO: add id later
cmd.Parameters.Add(
new SqlParameter("@SensorSerialNumber", SqlDbType.NVarChar, 50) { Value = sensorId });
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)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
public void MarkTestSetupIncomplete(string sensorId)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TestSetupsMarkIncomplete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@SensorId", SqlDbType.Int) { Value = null });
cmd.Parameters.Add(
new SqlParameter("@SensorSerialNumber", SqlDbType.NVarChar, 50) { Value = sensorId });
cmd.Parameters.Add(
new SqlParameter("@Message", SqlDbType.NVarChar, 255)
{
Value = "Some channels have no sensor assigned."
});
cmd.Parameters.Add(new SqlParameter("@TestSetupId", SqlDbType.NVarChar) { Value = null });
cmd.Parameters.Add(new SqlParameter("@TestSetupName", SqlDbType.NVarChar, 50) { Value = null });
#endregion
cmd.ExecuteNonQuery();
}
finally
{
cmd.Connection.Dispose();
}
}
}
#endregion Remove orphan records
public void Delete(SensorData sensor, bool bNotify)
{
lock (_lock)
{
var sensorType = (SensorDataType)(Convert.ToByte(sensor.IsDigitalInput()) +
(Convert.ToByte(sensor.IsDigitalOutput()) << 1) +
(Convert.ToByte(sensor.IsSquib()) << 2));
var sensorTypeParam = 0;
switch (sensorType)
{
case SensorDataType.Analog: sensorTypeParam = 0; break;
case SensorDataType.DigitalInput: sensorTypeParam = 1; break;
case SensorDataType.DigitalOutput: sensorTypeParam = 2; break;
case SensorDataType.Squib: sensorTypeParam = 3; break;
}
_ = DbOperations.SensorsDelete(sensor.DatabaseId, sensorTypeParam);
OnSensorsChanged?.Invoke(new[] { sensor }, true);
if (bNotify)
{
OnPropertyChanged("AllSensors");
}
}
}
public void Delete(SensorData[] sensors, bool bNotify)
{
foreach (var sensor in sensors)
{
Delete(sensor, bNotify);
}
}
/// <summary>
/// deletes all sensors
/// originally created so TDM imports could clear all tables except DAS tables.
/// </summary>
public void DeleteAll()
{
lock (_lock)
{
var hr = DbOperations.SensorsDeleteAll();
if (0 != hr)
{
APILogger.Log($"SensorsDeleteAll failed, result: {hr}");
return;
}
SensorCalibrationList.DeleteAll();
OnPropertyChanged("AllSensors");
}
}
/// <summary>
/// returns any non broken/do not use sensor with a given id in the database.
/// does not return any broken or do not use sensors
/// </summary>
/// <param name="id"></param>
/// <param name="bUseCache">whether to use test setup cached sensors or not</param>
/// <returns></returns>
public SensorData GetSensorByEId(string id, bool bUseCache = false)
{
if (bUseCache && null != _cachedSensors)
{
foreach (var sd in _cachedSensors)
{
if (sd.EID == id) { return sd; }
}
}
var allSensors = GetSensorsByEId(id);
if (allSensors.Any())
{
foreach (var sensor in allSensors)
{
if (sensor.Broken || sensor.DoNotUse) { continue; }
return sensor;
}
}
return null;
}
/// <summary>
/// returns sensors given an electronic sensor id
/// note there can be multiple ber electronic id now as Broken/DoNotUse allow this feature
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public SensorData[] GetSensorsByEId(string id)
{
var sensors = new List<SensorData>();
var hr = DbOperations.SensorsAnalogGet(null, null, id, out var records);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
var sd = new SensorData(record);
sensors.Add(sd);
}
}
hr = DbOperations.SensorsDigitalInGet(null, null, id, out var digitalIns);
if (0 == hr && null != digitalIns && digitalIns.Any())
{
foreach (var digitalIn in digitalIns)
{
sensors.Add(new DigitalInputSetting(digitalIn));
}
}
hr = DbOperations.SensorsSquibGet(null, null, id, out var squibRecords);
if (0 == hr && null != squibRecords && squibRecords.Any())
{
foreach (var squibRecord in squibRecords)
{
var squib = new SquibSetting(squibRecord);
sensors.Add(squib);
}
}
return sensors.ToArray();
}
public void Commit(string user, SensorData sd, bool bPublish = true)
{
Commit(user, sd, true, null, bPublish);
}
public void Commit(string user, SensorData sd, SensorCalibration sc, bool bPublish = true, bool bSetLatestCalId = false)
{
Commit(user, sd, true, sc, bPublish, bSetLatestCalId);
}
private static object _vm = null;
private void PublishCodes(Common.Events.ChannelCodes.ChannelCodeCommittedEventArgs[] args)
{
if (!System.Windows.Application.Current.Dispatcher.CheckAccess())
{
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { PublishCodes(args); }));
}
else
{
if (null == _vm)
{
//13868 Custom codes are added to a group, but does not appear in the channel codes tile
//make sure this vm is initialized and listening
var UnityContainer = ContainerLocator.Container.Resolve<IUnityContainer>();
_vm = UnityContainer.Resolve<IChannelCodesListViewModel>();
}
var eg = ContainerLocator.Container.Resolve<IEventAggregator>();
eg.GetEvent<Common.Events.ChannelCodes.ChannelCodeCommittedEvent>().Publish(args);
}
}
/// <summary>
/// indicates whether a user can commit channel codes or not
/// </summary>
public bool CanUserCommitChannelCodes { get; set; }
public void Commit(string user, SensorData sd, bool bNotify, SensorCalibration sc, bool bPublish = true, bool bSetLatestCalId = false)
{
var args =
new[]
{
new Common.Events.ChannelCodes.ChannelCodeCommittedEventArgs(
Common.Enums.Channels.ChannelEnumsAndConstants.ChannelCodeType.ISO, sd.ISOCode,
sd.ISOChannelName, CanUserCommitChannelCodes),
new Common.Events.ChannelCodes.ChannelCodeCommittedEventArgs(
Common.Enums.Channels.ChannelEnumsAndConstants.ChannelCodeType.User, sd.UserCode,
sd.UserChannelName, CanUserCommitChannelCodes)
};
if (bPublish)
{
//FB13262: only publish if we've fired up unity
PublishCodes(args);
}
sd.LastUpdatedBy = user;
sd.LastModified = DateTime.Now;
var existing = GetSensorBySerialNumber(sd.SerialNumber);
if (sd.IsDigitalInput())
{
if (null != existing && !existing.IsDigitalInput())
{
throw new Exception("can't change sensor to digital input");
}
CommitDigital(sd, bNotify);
}
else if (sd.IsDigitalOutput())
{
if (null != existing && !existing.IsDigitalOutput())
{
throw new Exception("can't change sensor to digital output");
}
CommitDigitalOutput(sd, bNotify);
}
else if (sd.IsSquib())
{
if (null != existing && !existing.IsSquib())
{
throw new Exception("can't change sensor to squib");
}
CommitSquib(sd, bNotify);
}
else if (sd.IsUart())
{
if (null != existing && !existing.IsUart())
{
throw new Exception("can't change sensor to uart");
}
CommitUart(sd, bNotify);
}
else if (sd.IsStreamOutput())
{
if (null != existing && !existing.IsStreamOutput())
{
throw new Exception("can't change sensor to stream output");
}
CommitStreamOutput(sd, bNotify);
}
else if (sd.IsStreamInput())
{
if (null != existing && !existing.IsStreamInput())
{
throw new Exception("can't change sensor to stream input");
}
CommitStreamInput(sd, bNotify);
}
else
{
CommitAnalog(sd, bNotify, sc, bSetLatestCalId);
}
}
/// <summary>
/// Returns True if the ID passed in is null,
/// or if there is no sensor with the ID passed in,
/// or if there is a sensor with the ID passed in which has the same Serial Number.
/// </summary>
/// <param name="serialNumber"></param>
/// <param name="id"></param>
/// <returns></returns>
public bool CanSensorIdBeAssigned(string serialNumber, string id)
{
// check if we're looking at an empty id first. http://fogbugz/fogbugz/default.asp?13552
if (string.IsNullOrEmpty(id)) return true;
var existing = GetSensorByEId(id);
if (null != existing && existing.SerialNumber != serialNumber)
{
return false;
}
return true;
}
/// <summary>
/// Returns True if the ID passed in is null,
/// or if there is no sensor with the ID passed in,
/// or if there is a sensor with the ID passed in which has the same Serial Number.
/// </summary>
/// <param name="serialNumber"></param>
/// <param name="id"></param>
/// <param name="existing">Returns the sensor found with the ID passed in, or null if no sensor found</param>
/// <returns></returns>
public bool CanSensorIdBeAssigned(string serialNumber, string id, out SensorData existing)
{
existing = null;
// check if we're looking at an empty id first. http://fogbugz/fogbugz/default.asp?13552
if (string.IsNullOrEmpty(id)) return true;
existing = GetSensorByEId(id);
if (null != existing && existing.SerialNumber != serialNumber)
{
return false;
}
return true;
}
// FB5438
public delegate void OnSensorsChangedHandler(SensorData[] sensors, bool bRemoved); // FB5438 & FB5023
// FB5438
public event OnSensorsChangedHandler OnSensorsChanged;
public void UpdateList()
{
OnPropertyChanged("AllSensors");
}
public bool SensorIdExists(string id)
{
if (string.IsNullOrWhiteSpace(id))
{
return false;
}
var existing = GetSensorByEId(id);
return null != existing;
}
private void DeleteIdInfo(SensorData sd)
{
}
private void AddIdInfo(SensorData sd)
{
if (string.IsNullOrWhiteSpace(sd.EID))
{
return;
}
var existing = GetSensorByEId(sd.EID);
if (null == existing)
{
return;
}
if (existing.SerialNumber == sd.SerialNumber)
{
return;
}
if (!(sd.Broken || sd.DoNotUse))
{
throw new NotSupportedException("Sensor IDs must be unique for active sensors in the sensor db");
}
}
/// <summary>
/// experimental, for bulk insert
/// </summary>
/// <param name="sd"></param>
/// <param name="bNotify"></param>
/// <param name="sc">Sensor Calibration</param>
/// <param name="bSetLatestCalId">Whether to set sensor's Latest Calibration Id when commiting</param>
private void CommitAnalog(SensorData sd, bool bNotify, SensorCalibration sc, bool bSetLatestCalId)
{
DeleteIdInfo(sd);
AddIdInfo(sd);
if (sd.Calibration.InitialOffsets.Offsets.Any())
{
sd.InitialEu = sd.Calibration.InitialOffsets.Offsets[0].EU;
}
else
{
sd.InitialEu = 0;
}
_ = DbOperations.SensorsAnalogInsertUpdate(sd);
if (sc != null)
{
var prevCal = SensorCalibrationList.GetLatestCalibrationBySerialNumber(sd);
if (null == prevCal)
{
// First Calibration
SensorCalibrationList.Commit(sc, true, sd, bSetLatestCalId);
}
else
{
// Does this new calibration differ from the old calibration (except for Usage Count)?
if (!prevCal.Equals(sd.Calibration))
{
//Reset Usage Count to 0 and commit the sensor calibration
sc.UsageCount = 0;
SensorCalibrationList.Commit(sc, true, sd, bSetLatestCalId);
//Set Usage Count to 0 for any sensors in the same Assembly
if (!string.IsNullOrWhiteSpace(sd.AssemblyName))
{
UpdateRelatedSensors(sd, sc.UsageCount);
}
}
else if (prevCal.UsageCount != sc.UsageCount)
{
//Only the Usage Count changed, so reflect that in any other sensors in the same Assembly
SensorCalibrationList.Commit(sc, true, sd, bSetLatestCalId);
if (!string.IsNullOrWhiteSpace(sd.AssemblyName))
{
UpdateRelatedSensors(sd, sc.UsageCount);
}
}
else if (SensorConstants.UseSensorFirstUseDate && sc.CalibrationId != null)
{
SetLatestCalId(sc, sd);
}
else
{
SensorData.SetSensitivityInspection(sd);
}
}
}
if (bNotify)
{
OnPropertyChanged("AllSensors");
}
}
private void UpdateRelatedSensors(SensorData sd, int usageCount)
{
var allSensors = SensorsList.GetAllSensors(true);
if ((allSensors != null) && (allSensors.Length > 0))
{
var sensorsInAssembly = allSensors.Where(sensor => sensor.AssemblyName == sd.AssemblyName);
if (sensorsInAssembly.Any())
{
foreach (var sensor in sensorsInAssembly)
{
//Make sure we don't update the original sensor calibration twice
if (sensor.SerialNumber != sd.SerialNumber)
{
_ = DbOperations.UpdateSensorCalibrationUsageCount(sensor.DatabaseId, (int)sensor.Calibration.CalibrationId, usageCount);
}
}
}
}
}
/// <summary>
/// updates the latest calibration id for the given sensor to the given calibration
/// 13065 Sensor "First Use" Date
/// </summary>
private void SetLatestCalId(SensorCalibration sc, SensorData sd)
{
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.StoredProcedure;
sql.CommandText = "sp_SensorsAnalogUpdateCalibrationId";
#region Parameters
sql.Parameters.Add(new SqlParameter("@SensorId", SqlDbType.Int) { Value = sd.DatabaseId });
sql.Parameters.Add(new SqlParameter("@LatestCalibrationId", SqlDbType.Int) { Value = sc.CalibrationId });
var errorNumber = new SqlParameter("@errorNumber", SqlDbType.Int)
{ Direction = ParameterDirection.Output };
sql.Parameters.Add(errorNumber);
var errorMessage = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 255)
{ Direction = ParameterDirection.Output };
sql.Parameters.Add(errorMessage);
#endregion Parameters
sql.ExecuteNonQuery();
if (!DBNull.Value.Equals(errorNumber.Value))
{
var error = Convert.ToInt32(errorNumber.Value);
if (0 != error)
{
throw new Exception($"Failed to set latest calibration id - {error} - {errorMessage.Value}");
}
}
}
finally
{
sql.Connection.Dispose();
}
}
}
private void CommitDigital(SensorData sd, bool bNotify)
{
DeleteIdInfo(sd);
AddIdInfo(sd);
DigitalInputSetting.Commit(sd);
if (bNotify)
{
OnPropertyChanged("AllSensors");
}
}
private void CommitDigitalOutput(SensorData sd, bool bNotify)
{
DeleteIdInfo(sd);
//no ids for douts
sd.EID = string.Empty;
AddIdInfo(sd);
DigitalOutputSetting.Commit(sd);
if (bNotify)
{
OnPropertyChanged("AllSensors");
}
}
private void CommitSquib(SensorData sd, bool bNotify)
{
//we shouldn't be allowed to save a sensor with no fire mode, so just force one to a default here.
if (sd.SquibFireMode == SquibFireMode.NONE)
{
sd.SquibFireMode = SquibFireMode.CAP;
}
//sd = new SquibSetting(sd);
SquibSetting.SetDefaults(sd);
DeleteIdInfo(sd);
AddIdInfo(sd);
SquibSetting.Commit(sd);
if (bNotify)
{
OnPropertyChanged("AllSensors");
}
}
private void CommitUart(SensorData sd, bool bNotify)
{
//sd = new UartSetting(sd);
UartSetting.SetDefaults(sd);
DeleteIdInfo(sd);
AddIdInfo(sd);
UartSetting.Commit(sd);
if (bNotify)
{
OnPropertyChanged("AllSensors");
}
}
private void CommitStreamOutput(SensorData sd, bool bNotify)
{
DeleteIdInfo(sd);
//no ids for streamouts
sd.EID = string.Empty;
AddIdInfo(sd);
StreamOutputSetting.Commit(sd);
if (bNotify)
{
OnPropertyChanged("AllSensors");
}
}
private void CommitStreamInput(SensorData sd, bool bNotify)
{
DeleteIdInfo(sd);
//no ids for streamins
sd.EID = string.Empty;
AddIdInfo(sd);
StreamInputSetting.Commit(sd);
if (bNotify)
{
OnPropertyChanged("AllSensors");
}
}
public static int ConvertBridgeToInt(SensorConstants.BridgeType bridge)
{
switch (bridge)
{
case SensorConstants.BridgeType.IEPE: return 0;
case SensorConstants.BridgeType.HalfBridge_SigPlus: return 4;
case SensorConstants.BridgeType.FullBridge: return 3;
case SensorConstants.BridgeType.HalfBridge: return 2;
case SensorConstants.BridgeType.QuarterBridge: return 1;
default: return 3;
}
}
public SensorData GetOriginalSensorBySensorDatabaseId(int databaseId)
{
if (databaseId <= 0) { return null; }
return new SensorData(GetSensorById(databaseId, false));
}
/// <summary>
/// retrieves a sensor given parameters
/// first looks for a sensor in cache, if using cache first looks for the original non modified version.
/// </summary>
/// <param name="serialNumber"></param>
/// <param name="excludeBroken"></param>
/// <param name="bUseCache"></param>
/// <returns></returns>
public SensorData GetOriginalSensorBySerialNumber(string serialNumber, bool excludeBroken = true, bool bUseCache = true)
{
if (string.IsNullOrWhiteSpace(serialNumber))
{
return null;
}
try
{
if (bUseCache && null != _originalCachedSensors)
{
var matches = from s in _originalCachedSensors where s.SerialNumber == serialNumber select s;
if (matches.Any())
{
return new SensorData(matches.First());
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
return new SensorData(GetSensorBySerialNumber(serialNumber, excludeBroken, bUseCache));
}
public SensorData GetSensorBySerialNumber(string serialNumber, bool excludeBroken = true, bool bUseCache = true)
{
if (string.IsNullOrWhiteSpace(serialNumber))
{
return null;
}
try
{
if (bUseCache && null != _cachedSensors)
{
var matches = from s in _cachedSensors where s.SerialNumber == serialNumber select s;
if (matches.Any())
{
return new SensorData(matches.First());
}
}
}
catch (Exception ex)
{
APILogger.Log("Failed to load Sensor: ", ex);
}
var sd = GetAnalogSensor(null, serialNumber, null);
if (null != sd)
{
if (sd.Broken && excludeBroken)
{
return null;
}
if (sd.DoNotUse && excludeBroken)
{
return null;
}
return sd;
}
sd = GetSquib(null, serialNumber, null);
if (null != sd)
{
if ((sd.Broken || sd.DoNotUse) && excludeBroken)
{
return null;
}
return sd;
}
sd = GetDigitalInput(null, serialNumber, null);
if (null != sd)
{
if ((sd.Broken || sd.DoNotUse) && excludeBroken)
{
return null;
}
return sd;
}
sd = GetDigitalOut(null, serialNumber);
if (null != sd)
{
if ((sd.Broken || sd.DoNotUse) && excludeBroken)
{
return null;
}
return sd;
}
sd = GetUartSetting(null, serialNumber);
if (null != sd)
{
if ((sd.Broken || sd.DoNotUse) && excludeBroken)
{
return null;
}
return sd;
}
sd = GetStreamOutput(null, serialNumber);
if (null != sd)
{
if ((sd.Broken || sd.DoNotUse) && excludeBroken)
{
return null;
}
return sd;
}
sd = GetStreamInput(null, serialNumber);
if (null != sd)
{
if ((sd.Broken || sd.DoNotUse) && excludeBroken)
{
return null;
}
return sd;
}
sd = GetThermocoupler(null, serialNumber);
if (null != sd)
{
if ((sd.Broken || sd.DoNotUse) && excludeBroken)
{
return null;
}
return sd;
}
sd = GetCanSetting(null, serialNumber);
if (null != sd)
{
if ((sd.Broken || sd.DoNotUse) && excludeBroken)
{
return null;
}
return sd;
}
if (SensorConstants.IsTestSpecificDigitalOut(serialNumber))
{
var dout = GetSensorBySerialNumber(SensorConstants.TEST_SPECIFIC_DIGITAL_OUT_SERIAL, excludeBroken, bUseCache);
dout.SerialNumber = serialNumber;
return dout;
}
if (SensorConstants.IsTestSpecificSquib(serialNumber))
{
var squib = GetSensorBySerialNumber(SensorConstants.TEST_SPECIFIC_SQUIB_SERIAL, excludeBroken, bUseCache);
squib.SerialNumber = serialNumber;
return squib;
}
if (SensorConstants.IsTestSpecificEmbedded(serialNumber) || SensorConstants.IsTestSpecificThermoCouple(serialNumber))
{
var aout = GetSensorBySerialNumber(SensorConstants.TEST_SPECIFIC_ANALOG_SERIAL, excludeBroken, bUseCache);
aout.SerialNumber = serialNumber;
return aout;
}
if (SensorConstants.IsTestSpecificUart(serialNumber))
{
var uart = GetSensorBySerialNumber(SensorConstants.TEST_SPECIFIC_UART_SERIAL, excludeBroken, bUseCache);
uart.SerialNumber = serialNumber;
return uart;
}
if (SensorConstants.IsTestSpecificStreamOut(serialNumber))
{
var sout = GetSensorBySerialNumber(SensorConstants.TEST_SPECIFIC_STREAM_OUT_SERIAL, excludeBroken, bUseCache);
sout.SerialNumber = serialNumber;
return sout;
}
if (SensorConstants.IsTestSpecificStreamIn(serialNumber))
{
var sin = GetSensorBySerialNumber(SensorConstants.TEST_SPECIFIC_STREAM_IN_SERIAL, excludeBroken, bUseCache);
sin.SerialNumber = serialNumber;
return sin;
}
if (SensorConstants.IsTestSpecificThermocoupler(serialNumber))
{
var stc = GetSensorBySerialNumber(SensorConstants.TEST_SPECIFIC_THERMOCOUPLER, excludeBroken, bUseCache);
stc.SerialNumber = serialNumber;
return stc;
}
if (SensorConstants.IsTestSpecificCAN(serialNumber))
{
var can = GetSensorBySerialNumber(SensorConstants.TEST_SPECIFIC_CAN_SERIAL, excludeBroken, bUseCache);
can.SerialNumber = serialNumber;
return can;
}
return null;
}
private static SensorData GetAnalogSensor(int? id, string serialNumber, string eid, IReadOnlyDictionary<string, SensorCalibration> calLookup = null)
{
var hr = DbOperations.SensorsAnalogGet(id, serialNumber, eid, out var records);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
return new SensorData(record, calLookup);
}
}
return null;
}
private static SensorData GetSquib(int? id, string serialNumber, string eid)
{
var hr = DbOperations.SensorsSquibGet(id, serialNumber, eid, out var records);
if (0 == hr && null != records && records.Any())
{
return new SquibSetting(records[0]);
}
return null;
}
private static SensorData GetDigitalInput(int? id, string serialNumber, string eid)
{
var hr = DbOperations.SensorsDigitalInGet(id, serialNumber, eid, out var records);
if (0 == hr && null != records && records.Any())
{
return new DigitalInputSetting(records[0]);
}
return null;
}
private static SensorData GetDigitalOut(int? id, string serialNumber)
{
var hr = DbOperations.SensorsDigitalOutGet(id, serialNumber, out var records);
if (0 == hr && null != records && records.Any())
{
return new DigitalOutputSetting(records[0]);
}
return null;
}
private static SensorData GetUartSetting(int? id, string serialNumber)
{
var hr = DbOperations.SensorsUARTGet(id, serialNumber, out var records);
if (0 == hr && null != records && records.Any())
{
var uart = new UartSetting(records[0]);
return uart;
}
return null;
}
private static SensorData GetStreamOutput(int? id, string serialNumber)
{
var hr = DbOperations.SensorsStreamOutputGet(id, serialNumber, out var records);
if (0 == hr && null != records && records.Any())
{
return new StreamOutputSetting(records[0]);
}
return null;
}
private static SensorData GetStreamInput(int? id, string serialNumber)
{
var hr = DbOperations.SensorsStreamInputGet(id, serialNumber, out var records);
if (0 == hr && null != records && records.Any())
{
return new StreamInputSetting(records[0]);
}
return null;
}
private static SensorData GetThermocoupler(int? id, string serialNumber)
{
var hr = DbOperations.SensorsThermocouplerGet(id, serialNumber, out var records);
if (0 == hr && null != records && records.Any())
{
return new ThermocouplerSetting(records[0]);
}
return null;
}
private static SensorData GetCanSetting(int? id, string serialNumber)
{
var hr = DbOperations.SensorsCANGet(id, serialNumber, out var records);
if (0 == hr && null != records && records.Any())
{
var can = new CanSetting(records[0]);
return can;
}
return null;
}
public SensorData GetSensorById(int id, bool bUseCache = true, IReadOnlyDictionary<string, SensorCalibration> calLookup = null)
{
try
{
//31738 Use cached sensors during Run Test
if (RunTestVariables.InRunTest && null != _cachedSensors && _cachedSensors.Any())
{
var s = Array.Find(_cachedSensors, sensor => sensor.DatabaseId == id);
if (null != s)
{
DbOperations.LogDBCaching("****** Using cached sensors in GetSensorById");
return new SensorData(s);
}
}
}
catch (Exception ex)
{
APILogger.Log("Failed to load Sensor: ", ex);
}
if (id < 0) { return null; }
//FB 18875 use cached sensor calibration
var sd = GetAnalogSensor(id, null, null, calLookup);
if (null != sd) { return sd; }
sd = GetSquib(id, null, null);
if (null != sd) { return sd; }
sd = GetDigitalInput(id, null, null);
if (null != sd) { return sd; }
sd = GetUartSetting(id, null);
if (null != sd) { return sd; }
sd = GetStreamOutput(id, null);
if (null != sd) { return sd; }
sd = GetStreamInput(id, null);
if (null != sd) { return sd; }
sd = GetThermocoupler(id, null);
if (null != sd) { return sd; }
sd = GetCanSetting(id, null);
if (null != sd) { return sd; }
return GetDigitalOut(id, null);
}
private static bool _cache = false;
/// <summary>
/// when there are a large number of test setups to validate, they each grab all the sensors
/// to avoid this they can be cached between validating all the test setups and save some time
/// </summary>
//public static bool Cache
//{
// get => _cache;
// set
// {
// _cache = value;
// if (!value)
// {
// _cachedSensorData = null;
// }
// }
//}
/// <summary>
/// this holds the cached sensors being used while many test setups are validated
/// </summary>
//private static SensorData [] _cachedSensorData;
private static bool _cacheCals = false;
private static IReadOnlyDictionary<string, SensorCalibration> _cachedCals = null;
public static void SetCached(bool bCached)
{
_cacheCals = bCached;
if (!bCached)
{
_cachedCals = null;
}
}
/// <summary>
/// gets all calibrations in a dictionary rather than getting 1 by 1
/// 17991 calspan speed ups for opening a test setup
/// returns the dictionary with just the latest calibrations keyed by sensor serial
/// </summary>
public static IReadOnlyDictionary<string, SensorCalibration> GetLatestCalibrations()
{
var dictionary = new Dictionary<string, SensorCalibration>();
if (RunTestVariables.InRunTest &&
_cachedCals != null &&
_cachedCals.Any())
{
DbOperations.LogDBCaching("****** Using cached calibrations in GetLatestCalibrations");
return _cachedCals;
}
var hr = DbOperations.SensorCalibrationsGet(null, null, out var records);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
var cal = new SensorCalibration(record);
if (dictionary.ContainsKey(cal.SerialNumber))
{
if (dictionary[cal.SerialNumber].CalibrationDate < cal.CalibrationDate)
{
dictionary[cal.SerialNumber] = cal;
}
else if (dictionary[cal.SerialNumber].CalibrationDate == cal.CalibrationDate)
{
if (dictionary[cal.SerialNumber].ModifyDate < cal.ModifyDate)
{
dictionary[cal.SerialNumber] = cal;
}
}
}
else
{
dictionary[cal.SerialNumber] = cal;
}
}
}
if (_cacheCals) { _cachedCals = dictionary; }
return dictionary;
}
public SensorData[] GetAllSensors(bool bIncludeBrokenAndDoNotUse)
{
var sensorDictionary = new Dictionary<string, SensorData>(20000);
var cals = GetLatestCalibrations();
if (RunTestVariables.InRunTest &&
_cachedSensors != null &&
_cachedSensors.Any())
{
DbOperations.LogDBCaching("****** Using cached sensors in GetAllSensors");
foreach (var sensor in _cachedSensors)
{
sensorDictionary.Add(sensor.SerialNumber, sensor);
}
var cacheList = new List<SensorData>(sensorDictionary.Values);
cacheList.Sort();
return cacheList.ToArray();
}
var hr = DbOperations.SensorsAnalogGet(null, null, null, out var records);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
var sd = new SensorData(record, cals);
if (!bIncludeBrokenAndDoNotUse && (sd.DoNotUse || sd.Broken))
{
continue;
}
try
{
if (!sensorDictionary.ContainsKey(sd.SerialNumber))
{
//FB14606: fetch latest calibration for initializing zeromethod, other variables
if (cals.ContainsKey(sd.SerialNumber))
{
sd.Calibration = cals[sd.SerialNumber];
}
else { sd.Calibration = sd.GetLatestCalibration(); }
sensorDictionary.Add(sd.SerialNumber, sd);
if (sd.Calibration != null)
{
record.UsageCount = sd.Calibration.UsageCount;
}
if (string.IsNullOrEmpty(sd.EID)) continue;
}
}
catch (Exception ex)
{
APILogger.Log("Failed to load sensor: ", ex);
}
}
}
try
{
var settings = new List<DigitalInputSetting>();
hr = DbOperations.SensorsDigitalInGet(null, null, null, out var digitalIns);
if (0 == hr && null != digitalIns && digitalIns.Any())
{
foreach (var record in digitalIns)
{
var digitalIn = new DigitalInputSetting(record);
if (!bIncludeBrokenAndDoNotUse && (digitalIn.Broken || digitalIn.DoNotUse))
{
continue;
}
settings.Add(digitalIn);
}
}
foreach (var s in settings)
{
if (sensorDictionary.ContainsKey(s.SerialNumber))
{
//don't load it, just ignore the setting
}
else
{
sensorDictionary[s.SerialNumber] = s;
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
try
{
var settings = new List<SquibSetting>();
hr = DbOperations.SensorsSquibGet(null, null, null, out var squibRecords);
if (0 == hr && null != squibRecords && squibRecords.Any())
{
foreach (var squibRecord in squibRecords)
{
var setting = new SquibSetting(squibRecord);
if (!bIncludeBrokenAndDoNotUse && (setting.Broken || setting.DoNotUse))
{
continue;
}
settings.Add(setting);
}
}
foreach (var s in settings)
{
if (sensorDictionary.ContainsKey(s.SerialNumber))
{
//serial number already exists as something else, ignore this one!
}
else
{
sensorDictionary[s.SerialNumber] = s;
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
try
{
var lDOS = new List<DigitalOutputSetting>();
hr = DbOperations.SensorsDigitalOutGet(null, null, out var digitalOutDbRecords);
if (0 == hr && null != digitalOutDbRecords && digitalOutDbRecords.Any())
{
foreach (var record in digitalOutDbRecords)
{
var setting = new DigitalOutputSetting(record);
if (!bIncludeBrokenAndDoNotUse && (setting.Broken || setting.DoNotUse))
{
continue;
}
lDOS.Add(setting);
}
}
foreach (var s in lDOS)
{
if (!sensorDictionary.ContainsKey(s.SerialNumber))
{
sensorDictionary[s.SerialNumber] = s;
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
try
{
var lUART = new List<UartSetting>();
hr = DbOperations.SensorsUARTGet(null, null, out var uartRecords);
if (0 == hr && null != uartRecords && uartRecords.Any())
{
foreach (var record in uartRecords)
{
var setting = new UartSetting(record);
if (!bIncludeBrokenAndDoNotUse && (setting.Broken || setting.DoNotUse))
{
continue;
}
lUART.Add(setting);
}
}
foreach (var s in lUART)
{
if (!sensorDictionary.ContainsKey(s.SerialNumber))
{
sensorDictionary[s.SerialNumber] = s;
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
try
{
var lSOS = new List<StreamOutputSetting>();
hr = DbOperations.SensorsStreamOutputGet(null, null, out var outputRecords);
if (0 == hr && null != outputRecords && outputRecords.Any())
{
foreach (var record in outputRecords)
{
if (!bIncludeBrokenAndDoNotUse && (record.Broken || record.DoNotUse))
{
continue;
}
lSOS.Add(new StreamOutputSetting(record));
}
}
foreach (var s in lSOS)
{
if (!sensorDictionary.ContainsKey(s.SerialNumber))
{
sensorDictionary[s.SerialNumber] = s;
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
try
{
var lSOS = new List<StreamInputSetting>();
hr = DbOperations.SensorsStreamInputGet(null, null, out var outputRecords);
if (0 == hr && null != outputRecords && outputRecords.Any())
{
foreach (var record in outputRecords)
{
if (!bIncludeBrokenAndDoNotUse && (record.Broken || record.DoNotUse))
{
continue;
}
lSOS.Add(new StreamInputSetting(record));
}
}
foreach (var s in lSOS)
{
if (!sensorDictionary.ContainsKey(s.SerialNumber))
{
sensorDictionary[s.SerialNumber] = s;
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
try
{
var lCAN = new List<CanSetting>();
hr = DbOperations.SensorsCANGet(null, null, out var canRecords);
if (0 == hr && null != canRecords && canRecords.Any())
{
foreach (var record in canRecords)
{
var setting = new CanSetting(record);
if (!bIncludeBrokenAndDoNotUse && (setting.Broken || setting.DoNotUse))
{
continue;
}
lCAN.Add(setting);
}
}
foreach (var s in lCAN)
{
if (!sensorDictionary.ContainsKey(s.SerialNumber))
{
sensorDictionary[s.SerialNumber] = s;
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
var list = new List<SensorData>(sensorDictionary.Values);
list.Sort();
if (RunTestVariables.InRunTest)
{
_cachedSensors = list.ToArray();
}
else
{
_cachedSensors = null;
}
return list.ToArray();
}
}
}