This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,427 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using DTS.Common.Enums;
using DTS.Common.Interface.Sensors;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
namespace DTS.SensorDB
{
public class SensorCalibrationList
{
private static List<SensorCalibration> _cachedCalibrations = null;
public static void SetCachedCalibrations(SensorCalibration[] cachedCals)
{
_cachedCalibrations = null == cachedCals ? null : new List<SensorCalibration>(cachedCals);
}
public static void ClearCachedCalibrations()
{
_cachedCalibrations = null;
_calibrationList?._calibrations?.Clear();
}
// I'm not sure we ever want to call this constructor? we probably always want to get all?
//22287 Calibration error in Edit Test Setup when DataPRO is initiated and Sensors tab is not clicked first.
//private SensorCalibrationList(string sensorSerialNumber)
//{
// _calibrations = new Dictionary<string, List<SensorCalibration>>();
// var hr = DbOperations.SensorCalibrationsGet(null, sensorSerialNumber, out var records);
// if( 0 == hr && null != records && records.Any())
// {
// foreach( var record in records)
// {
// var sc = new SensorCalibration(record);
// if (!_calibrations.ContainsKey(sc.SerialNumber))
// {
// _calibrations.Add(sc.SerialNumber, new List<SensorCalibration>());
// }
// _calibrations[sc.SerialNumber].Add(sc);
// }
// }
//}
protected SensorCalibrationList(ISensorCalDbRecord[] records)
{
_calibrations = new Dictionary<string, List<SensorCalibration>>();
if (null != records && records.Any())
{
foreach (var record in records)
{
var sc = new SensorCalibration(record);
if (!_calibrations.ContainsKey(sc.SerialNumber))
{
_calibrations.Add(sc.SerialNumber, new List<SensorCalibration>());
}
_calibrations[sc.SerialNumber].Add(sc);
}
}
}
private readonly Dictionary<string, List<SensorCalibration>> _calibrations;
private static readonly object LOCK = new object();
private static SensorCalibrationList _calibrationList;
public static void Reload()
{
lock (LOCK)
{
_calibrationList = new SensorCalibrationList(GetSensorCalibrationsFromDb());
}
}
public static void Reload(ISensorCalDbRecord[] records)
{
lock (LOCK)
{
_calibrationList = new SensorCalibrationList(records);
}
}
public static ISensorCalDbRecord[] GetSensorCalibrationsFromDb()
{
var hr = DbOperations.SensorCalibrationsGet(null, null, out var records);
if (hr == 0) { return records; }
return new ISensorCalDbRecord[0];
}
public static SensorCalibration GetLatestCalibrationBySerialNumber(SensorData sd, ISensorCalDbRecord[] sensorCalDbRecords = null)
{
if (null == sd) { return null; }
if (sd.IsDigitalInput() || sd.IsSquib() || sd.IsDigitalOutput()) { return SensorCalibration.NewDigitalSC(sd.IsDigitalInput() ? sd.DIUnits : "V"); }
if (null != _cachedCalibrations)
{
var matches = from sc in _cachedCalibrations where sc.SerialNumber == sd.SerialNumber select sc;
var sensorCalibrations = matches as SensorCalibration[] ?? matches.ToArray();
if (sensorCalibrations.Any())
{
return ValidateAndGetSensorCalibrationFromCache(sensorCalibrations);
}
}
lock (LOCK)
{
AssignCalibrationListFromFb(ref sensorCalDbRecords);
if (_calibrationList._calibrations.ContainsKey(sd.SerialNumber) && _calibrationList._calibrations[sd.SerialNumber].Count > 0)
{
return ValidateAndGetSensorCalibration(sd);
}
return null;
}
}
private static SensorCalibration ValidateAndGetSensorCalibrationFromCache(SensorCalibration[] sensorCalibrations)
{
SensorCalibration cal = null;
foreach (var sc in sensorCalibrations)
{
if (null == cal || cal.CalibrationDate < sc.CalibrationDate || cal.CalibrationDate == sc.CalibrationDate && cal.ModifyDate < sc.ModifyDate) { cal = sc; }
}
return cal;
}
private static void AssignCalibrationListFromFb(ref ISensorCalDbRecord[] sensorCalDbRecords)
{
if ((null == _calibrationList) || (_calibrationList._calibrations == null) || (!_calibrationList._calibrations.Any()))
{
if (sensorCalDbRecords == null)
{
sensorCalDbRecords = GetSensorCalibrationsFromDb();
}
_calibrationList = new SensorCalibrationList(sensorCalDbRecords);
}
}
private static SensorCalibration ValidateAndGetSensorCalibration(SensorData sd)
{
try
{
var item = _calibrationList._calibrations[sd.SerialNumber].Aggregate((i1, i2) =>
{
if (i1.CalibrationDate > i2.CalibrationDate)
{
return i1;
}
else
{
return i1.CalibrationDate == i2.CalibrationDate && i1.ModifyDate > i2.ModifyDate ? i1 : i2;
}
});
return new SensorCalibration(item);//for safety reasons, don't return the original
}
catch (Exception ex)
{
APILogger.Log(ex);
}
return null;
}
public static SensorCalibration NewEmbeddedSC(string units)
{
return SensorCalibration.NewEmbeddedSC(units);
}
public static SensorCalibration GetLatestCalibrationBySerialNumberAndExcitation(SensorData sd, ExcitationVoltageOptions.ExcitationVoltageOption exc)
{
if (null == sd) { return null; }
if (sd.IsDigitalInput() || sd.IsSquib() || sd.IsDigitalOutput()) { return SensorCalibration.NewDigitalSC(sd.IsDigitalInput() ? sd.DIUnits : "V"); }
if (sd.IsTestSpecificEmbedded) { return SensorCalibration.NewEmbeddedSC(sd.Calibration?.EngineeringUnits ?? "V"); } //TODO: REMOVE THIS HACK when we have proper get cal functions
if (sd.IsTestSpecificThermo) { return SensorCalibration.NewEmbeddedSC(sd.Calibration?.EngineeringUnits ?? "C"); }
if (null != _cachedCalibrations && _cachedCalibrations.Any())
{
var matches = from sc in _cachedCalibrations where sc.SerialNumber == sd.SerialNumber select sc;
var sensorCalibrations = matches as SensorCalibration[] ?? matches.ToArray();
if (sensorCalibrations.Any())
{
SensorCalibration cal = null;
foreach (var sc in sensorCalibrations)
{
if (sc.IsProportional)
{
var bOk = Array.Exists(sc.Records.Records, record => record.Excitation == exc);
if (!bOk) { continue; }
}
if (null == cal) { cal = sc; }
else if (sc.CalibrationDate > cal.CalibrationDate) { cal = sc; }
else if (sc.CalibrationDate == cal.CalibrationDate && sc.ModifyDate > cal.ModifyDate)
{
cal = sc;
}
}
if (null != cal) { return cal; }
}
}
lock (LOCK)
{
if (null == _calibrationList || 0 == _calibrationList._calibrations.Count)
{
_calibrationList = new SensorCalibrationList(GetSensorCalibrationsFromDb());
}
if (!_calibrationList._calibrations.ContainsKey(sd.SerialNumber) || _calibrationList._calibrations[sd.SerialNumber].Count <= 0) return null;
try
{
var list = _calibrationList._calibrations[sd.SerialNumber];
list.Sort();
foreach (var sc in list)
{
if (!sc.IsProportional) { return new SensorCalibration(sc); }
if (Array.Exists(sc.Records.Records, record => record.Excitation == exc))
{
return new SensorCalibration(sc);
}
}
}
catch (Exception ex) { APILogger.Log(ex); }
return null;
}
}
public static SensorCalibration GetLatestCalibrationsBySerialNumberAndCalDate(string ser, DateTime calDate)
{
if (null == _calibrationList)
{
_calibrationList = new SensorCalibrationList(GetSensorCalibrationsFromDb());
}
if (!_calibrationList._calibrations.ContainsKey(ser) || _calibrationList._calibrations[ser].Count <= 0)
return null;
try
{
var list = new List<SensorCalibration>(_calibrationList._calibrations[ser]);
for (var i = list.Count - 1; i >= 0; i--)
{
if (list[i].CalibrationDate != calDate) { list.RemoveAt(i); }
}
if (list.Count <= 0) return null;
list.Sort();
return new SensorCalibration(list[0]);
}
catch (Exception ex) { APILogger.Log(ex); }
return null;
}
public static SensorCalibration GetLatestCalibrationsBySerialNumberCalDateAndModifyDate(string ser, DateTime calDate, DateTime modifyDate)
{
if (null == _calibrationList)
{
_calibrationList = new SensorCalibrationList(GetSensorCalibrationsFromDb());
}
if (_calibrationList._calibrations.ContainsKey(ser) && _calibrationList._calibrations[ser].Count > 0)
{
try
{
var list = new List<SensorCalibration>(_calibrationList._calibrations[ser]);
for (var i = list.Count - 1; i >= 0; i--)
{
if (list[i].CalibrationDate != calDate)
{
list.RemoveAt(i);
}
else
{
//12488 Import Test Setup adds new sensor calibration entries every time
//note that modify date as datetime can have more deviation than cal dates, which are just date
//so we have to consider the minimum varation between time, which I set to 1 second here
var delta = list[i].ModifyDate.Subtract(modifyDate);
if (Math.Abs(delta.TotalSeconds) >= 1)
{
list.RemoveAt(i);
}
}
}
if (list.Count <= 0) return null;
list.Sort();
return new SensorCalibration(list[0]);
}
catch (Exception ex) { APILogger.Log(ex); }
return null;
}
return null;
}
public static SensorCalibration[] GetCalibrationsBySerialNumber(SensorData sd)
{
if (null == sd) { return new SensorCalibration[0]; }
if (sd.IsDigitalInput() || sd.IsSquib() || sd.IsDigitalOutput()) { return new[] { SensorCalibration.NewDigitalSC(sd.IsDigitalInput() ? sd.DIUnits : "V") }; }
if (null != _cachedCalibrations)
{
var matches = from sc in _cachedCalibrations where sd.SerialNumber == sc.SerialNumber select sc;
var sensorCalibrations = matches as SensorCalibration[] ?? matches.ToArray();
if (sensorCalibrations.Any())
{
return sensorCalibrations.ToArray();
}
}
lock (LOCK)
{
if (null == _calibrationList || 0 == _calibrationList._calibrations.Count)
{
_calibrationList = new SensorCalibrationList(GetSensorCalibrationsFromDb());
}
if (!_calibrationList._calibrations.ContainsKey(sd.SerialNumber)) return new SensorCalibration[0];
var list = new List<SensorCalibration>(_calibrationList._calibrations[sd.SerialNumber].Count);
list.AddRange(_calibrationList._calibrations[sd.SerialNumber].Select(sc => new SensorCalibration(sc)));
return list.ToArray();
}
}
/// <summary>
/// commits a sensor to the db
/// </summary>
/// <param name="sc"></param>
/// <param name="bChangeModifyDate"></param>
/// <param name="sd"></param>
/// <param name="bSetLatestCalId">whether to set the calibration id on the sensor to the sensor calibration when the calibration is committed</param>
public static void Commit(SensorCalibration sc, bool bChangeModifyDate, SensorData sd, bool bSetLatestCalId = false)
{
try
{
if (sd.IsDigitalInput() || sd.IsDigitalOutput() || sd.IsSquib()
|| sd.IsStreamOutput() || sd.IsStreamInput() || sd.IsUart()) { return; }
if (null == sc) { return; }
SensorCalibration scExisting = null;
if (!bChangeModifyDate) { scExisting = GetLatestCalibrationsBySerialNumberCalDateAndModifyDate(sc.SerialNumber, sc.CalibrationDate, sc.ModifyDate); }
if (null != scExisting && sc.Equals(scExisting)) { return; }//no update needed
if (string.IsNullOrEmpty(sc.SerialNumber)) { return; }//don't commit a calibration without a serialnumber
//correct units capitalization if needed
foreach (var record in sc.Records.Records)
{
var units = MeasurementUnitList.GetMeasurementUnit(record.EngineeringUnits);
if (null != units && units.MainDisplayUnit != record.EngineeringUnits) { record.EngineeringUnits = units.MainDisplayUnit; }
}
sc.Username = string.Empty;
if (null != DbOperations.CurrentUserDbRecord) { sc.Username = DbOperations.CurrentUserDbRecord.UserName; }
sc.Insert(bChangeModifyDate, sd, bSetLatestCalId);
if (!_calibrationList._calibrations.ContainsKey(sc.SerialNumber)) { _calibrationList._calibrations.Add(sc.SerialNumber, new List<SensorCalibration>()); }
_calibrationList._calibrations[sc.SerialNumber].Add(new SensorCalibration(sc));
}
// ReSharper disable once PossibleNullReferenceException
catch (Exception ex) { APILogger.Log("Failed to write sensor calibration", sc.SerialNumber, ex); }
}
/// <summary>
/// deletes all calibration data
/// originally created so TDM imports could clear all tables except DAS tables
/// </summary>
public static void DeleteAll()
{
try
{
var hr = DbOperations.SensorCalibrationsDelete(null, null, null);
if (0 != hr) { return; }
lock (LOCK)
{
if (null == _calibrationList)
{
_calibrationList = new SensorCalibrationList(GetSensorCalibrationsFromDb());
}
_calibrationList._calibrations.Clear();
}
}
catch (Exception ex) { APILogger.Log("Failed to delete sensor calibrations ", ex); }
}
/// <summary>
/// Deletes Calibration records from the database and Calibration List dictionary that match the serialNumber param
/// </summary>
/// <param name="serialNumber"></param>
public static void DeleteCalsBySerialNumber(string serialNumber)
{
// 6853 - Sensitivities are lost when importing SLICEWare sensors.
try
{
var hr = DbOperations.SensorCalibrationsDelete(serialNumber, null, null);
if (0 != hr)
{
APILogger.Log("Failed to delete sensor calibration ", serialNumber, hr);
return;
}
lock (LOCK)
{
if (null == _calibrationList) { _calibrationList = new SensorCalibrationList(GetSensorCalibrationsFromDb()); }
if (!_calibrationList._calibrations.ContainsKey(serialNumber)) return;
for (var i = _calibrationList._calibrations[serialNumber].Count - 1; i >= 0; i--) { _calibrationList._calibrations[serialNumber].RemoveAt(i); }
}
}
catch (Exception ex) { APILogger.Log("Failed to delete sensor calibration ", serialNumber, ex); }
}
public static void Delete(SensorCalibration sc)
{
try
{
var hr = DbOperations.SensorCalibrationsDelete(sc.SerialNumber, sc.CalibrationDate.Date, sc.ModifyDate);
if (0 != hr)
{
APILogger.Log("Failed to delete sensor calibration ", sc.SerialNumber, sc.CalibrationDate.ToShortDateString(), sc.ModifyDate.ToString(CultureInfo.InvariantCulture), hr);
return;
}
lock (LOCK)
{
if (null == _calibrationList)
{
_calibrationList = new SensorCalibrationList(GetSensorCalibrationsFromDb());
}
if (!_calibrationList._calibrations.ContainsKey(sc.SerialNumber)) return;
for (var i = _calibrationList._calibrations[sc.SerialNumber].Count - 1; i >= 0; i--)
{
if (_calibrationList._calibrations[sc.SerialNumber][i].CalibrationDate != sc.CalibrationDate ||
_calibrationList._calibrations[sc.SerialNumber][i].ModifyDate != sc.ModifyDate) continue;
_calibrationList._calibrations[sc.SerialNumber].RemoveAt(i);
break;
}
}
}
catch (Exception ex) { APILogger.Log("Failed to delete sensor calibration ", sc.SerialNumber, sc.CalibrationDate.ToShortDateString(), sc.ModifyDate.ToString(CultureInfo.InvariantCulture), ex); }
}
}
}