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 { /// /// these are sensors unmodified from a cache /// private SensorData[] _originalCachedSensors = new SensorData[0]; /// /// these are sensors modified from a cache (channel settings applied) /// 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]; } /// /// sets the cache of current sensors /// to be used when GetSensor is called with UseCache as true /// /// sensors to cache (with channel settings already applied) /// sensors cached unadulterated (to show differences in the UI, etc) public void SetCache(SensorData[] cachedSensors, SensorData[] originalCachedSensors) { _cachedSensors = cachedSensors; _originalCachedSensors = originalCachedSensors; } public event PropertyChangedEventHandler PropertyChanged; protected bool SetProperty(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().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); } } /// /// deletes all sensors /// originally created so TDM imports could clear all tables except DAS tables. /// public void DeleteAll() { lock (_lock) { var hr = DbOperations.SensorsDeleteAll(); if (0 != hr) { APILogger.Log($"SensorsDeleteAll failed, result: {hr}"); return; } SensorCalibrationList.DeleteAll(); OnPropertyChanged("AllSensors"); } } /// /// 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 /// /// /// whether to use test setup cached sensors or not /// 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; } /// /// returns sensors given an electronic sensor id /// note there can be multiple ber electronic id now as Broken/DoNotUse allow this feature /// /// /// public SensorData[] GetSensorsByEId(string id) { var sensors = new List(); 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(); _vm = UnityContainer.Resolve(); } var eg = ContainerLocator.Container.Resolve(); eg.GetEvent().Publish(args); } } /// /// indicates whether a user can commit channel codes or not /// 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); } } /// /// 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. /// /// /// /// 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; } /// /// 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. /// /// /// /// Returns the sensor found with the ID passed in, or null if no sensor found /// 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"); } } /// /// experimental, for bulk insert /// /// /// /// Sensor Calibration /// Whether to set sensor's Latest Calibration Id when commiting 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); } } } } } /// /// updates the latest calibration id for the given sensor to the given calibration /// 13065 Sensor "First Use" Date /// 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)); } /// /// retrieves a sensor given parameters /// first looks for a sensor in cache, if using cache first looks for the original non modified version. /// /// /// /// /// 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 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 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; /// /// 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 /// //public static bool Cache //{ // get => _cache; // set // { // _cache = value; // if (!value) // { // _cachedSensorData = null; // } // } //} /// /// this holds the cached sensors being used while many test setups are validated /// //private static SensorData [] _cachedSensorData; private static bool _cacheCals = false; private static IReadOnlyDictionary _cachedCals = null; public static void SetCached(bool bCached) { _cacheCals = bCached; if (!bCached) { _cachedCals = null; } } /// /// 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 /// public static IReadOnlyDictionary GetLatestCalibrations() { var dictionary = new Dictionary(); 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(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(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(); 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(); 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(); 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(); 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(); 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(); 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(); 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(sensorDictionary.Values); list.Sort(); if (RunTestVariables.InRunTest) { _cachedSensors = list.ToArray(); } else { _cachedSensors = null; } return list.ToArray(); } } }