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,150 @@
using DASFactoryDb.Diagnostics;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Interface.DASFactory.Diagnostics;
using DTS.Common.Utilities.Logging;
using System;
using System.Data.SqlClient;
using System.Linq;
namespace DTS.DASLib.Service
{
/// <summary>
/// This class holds instructions about how a single channel
/// is to be diagnosed. The results from these tests will populate the
/// DiagnosticsResults[] object in the IDASCommunication object. The results
/// can then be compared against the hardware specifications for a sensor to
/// determine if the channel is set up correctly before arming and recording.
/// </summary>
public class DiagnosticsActions : IDiagnosticActions
{
/// <summary>
/// Which DAS Channel (CH# WRT entire DAS unit) are these diagnostic test
/// instructions for?
/// </summary>
public int DASChannelNumber { get; set; }
/// <summary>
/// Should we measure the excitation volatge being applied to this sensor?
/// </summary>
public bool MeasureExcitation { get; set; }
/// <summary>
/// Should we measure the sensor's offset from 0? (If measured, the returned offset can
/// be checked against the high and low offset limits that are properties of the
/// AnalogInputDasChannel object corresponding to this sensor.)
/// </summary>
public bool MeasureOffset { get; set; }
/// <summary>
/// should we check the open/closed/low/high nature of a digital input channel?
/// </summary>
public bool CheckDigitalState { get; set; }
public bool MeasureInternalOffset { get; set; }
/// <summary>
/// Should the firmware compensate for the offset from 0 of this sensor?
/// </summary>
public bool RemoveOffset { get; set; }
/// <summary>
/// Should we measure the noise floor as a percentage of full scale readings?
/// </summary>
public bool MeasureNoise { get; set; }
/// <summary>
/// Should an emulated shunt-check be performed on this sensor.
/// </summary>
public bool PerformShuntCheck { get; set; }
/// <summary>
/// should run a squib fire check on channel
/// </summary>
public bool SquibFireCheck { get; set; } = false;
/// <summary>
/// perform a voltage insertion gain check (SLICE Pro)
/// </summary>
public bool PerformVoltageInsertCheck { get; set; }
/// <summary>
/// Should a Calibration signal-check be performed on this sensor.
/// </summary>
public bool PerformCalSignalCheck { get; set; }
/// <summary>
/// Should the resistance of the bridge be measured?
/// </summary>
public bool MeasureBridgeResistance { get; set; }
public DiagnosticsActions()
{
DASChannelNumber = 0;
MeasureExcitation = false;
MeasureOffset = false;
RemoveOffset = false;
MeasureNoise = false;
PerformShuntCheck = false;
PerformCalSignalCheck = false;
PerformVoltageInsertCheck = false;
MeasureInternalOffset = false;
CheckDigitalState = false;
}
public bool AllActionsDisabled()
{
return !MeasureExcitation && !MeasureOffset && !RemoveOffset && !MeasureNoise && !PerformShuntCheck &&
!MeasureBridgeResistance
&& !PerformCalSignalCheck && !PerformVoltageInsertCheck && !MeasureInternalOffset && !SquibFireCheck &&
!CheckDigitalState;
}
public static void SetChannelDiagnosticActions(IDASCommunication unit, IDiagnosticActions[] actions,
bool setInDb)
{
unit.ChannelDiagnostics = actions;
if (!DASFactoryDb.DbWrapper.Connected || !setInDb) { return; }
try
{
Diagnostics.ClearDiagnosticActionsAllChannels(unit.RecordId);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
if (null != actions)
{
foreach (var action in actions)
{
InsertAction(unit.RecordId, action);
}
}
}
private static void InsertAction(int dasRecordId, IDiagnosticActions action)
{
try
{
Diagnostics.InsertDiagnosticAction(dasRecordId,
action.DASChannelNumber,
action.MeasureExcitation,
action.MeasureOffset,
action.CheckDigitalState,
action.MeasureInternalOffset,
action.RemoveOffset,
action.MeasureNoise,
action.PerformShuntCheck,
action.SquibFireCheck,
action.PerformVoltageInsertCheck,
action.PerformCalSignalCheck,
action.MeasureBridgeResistance);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
}
}

View File

@@ -0,0 +1,194 @@
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.DASFactory.Diagnostics;
namespace DTS.DASLib.Service
{
/// <summary>
/// This class holds the results from one channel's diagnostics. These results are arbitrary on
/// thier own but can be checked against the hardware specifications or settings for the sensor on the
/// corresponding channel to provide pre-recording checks or diagnostic feedback about how the channel is
/// set up. For example this DiagnosticsResult will provide the acutal voltage that is being applied to
/// sensor for excitation, and this can be verified correct or incorrect based on what the sensor
/// actually needs for excitation. The sensor specific values can be found in the corresponding DASChannel
/// (<see cref="AnalogInputDASChannel" />) object in the ConfigData object for the IDASCommunication where this channel lives,
/// but they must be put there by a call to ConfigureService.Configure(...).
/// </summary>
public class DiagnosticsResult : IDiagnosticResult
{
/// <summary>
/// Which DASChannel from which this diagnostics is returning.
/// </summary>
public int DASChannelNumber { get; set; }
/// <summary>
/// The event number that this diagnostics is relevant for.
/// </summary>
public int EventNumber { get; set; }
/// <summary>
/// The firmware calculates a scale factory for the channel's input. The hardware will
/// deliver raw, unprocessed data upon download, but to diagnos this data to
/// reflect real world votages it must be scaled based on the DAS unit's factory
/// diagnostics as well as results from this diagnose. The samples that
/// will be downloaded will be straight from the A to D Converter so this scale
/// factor is MANDATORY and must be used at the software level to scale the data
/// to the real sensed voltages and engineering units.
/// </summary>
public double ScalefactorMilliVoltsPerADC { get; set; } = 1;
public double ScalefactorEngineeringUnitsPerADC { get; set; } = 1;
/// <summary>
/// The factory excitation value (mandatory)
/// </summary>
public double ExpectedExcitationMilliVolts { get; set; }
/// <summary>
/// gets what will probably be the datazerolevel adc for the channel
/// </summary>
/// <param name="zeroMethod"></param>
/// <returns></returns>
public short GetExpectedDataZeroLevelADC(ZeroMethodType zeroMethod)
{
switch (zeroMethod)
{
case ZeroMethodType.None:
return ZeroMVInADC;
default:
// if FinalOffsetADC is NOT null, offset has been measured after calibration
// and that's the amount is what we should use
if (FinalOffsetADC != null)
{
return (short)FinalOffsetADC;
}
// OK, FinalOffsetADC was null so we need to check MeasuredOffsetMilliVolts
// if it's NOT null, that's what we'll use
if (MeasuredOffsetMilliVolts != null)
{
return (short)((double)MeasuredOffsetMilliVolts / ScalefactorMilliVoltsPerADC);
}
// both of them are null so the only thing we can do is return 0
return 0;
}
}
/// <summary>
/// Excitation voltage provided to sensor as measured by the firmware during
/// calibration. When read from event attributes, a value of 0.0 might actually
/// mean null (i.e. was not measured).
/// </summary>
public double? MeasuredExcitationMilliVolts { get; set; }
/// <summary>
/// flag to indicate whether MeasuredExcitationMilliVolts was negative when it was initially read
/// 14233 Negative Excitation Reported by TDAS hardware not showing in Diagnostics
/// this was created to relate to legacy TDC/TDAS broken sensor/wire warnings carried through
/// the excitation reading
/// </summary>
public bool NegativeExcitation { get; set; }
/// <summary>
/// What is the sensor's offset reading from the 0 level? This is measured by firmware
/// during the calibration. When read from event attributes, a value of 0.0 might actually
/// mean null (i.e. was not measured).
/// </summary>
public double? MeasuredOffsetMilliVolts { get; set; }
public double? MeasuredInternalOffsetMilliVolts { get; set; }
/// <summary>
/// What is the sensor's offset reading from the 0 level? This is measured by firmware
/// during the calibration. When read from event attributes, a value of 0.0 might actually
/// mean null (i.e. was not measured).
/// </summary>
public double? MeasuredOffsetEngineeringUnits { get; set; }
/// <summary>
/// when a channel is autozero'd (remove offset)
/// this is the devation from 0 (from RW Auto zero is checking for +/- 5% from 0 in counts.)
/// </summary>
private double? _autoZeroPercentDeviation;
public double? AutoZeroPercentDeviation
{
get => _autoZeroPercentDeviation;
set => _autoZeroPercentDeviation = null != value ? (double?)System.Math.Abs((double)value) : null;
}
/// <summary>
/// If the <see cref="DTS.DASLib.Service.DiagnosticsService" />.Calibrate method was called with the "RemoveOffset" boolean variable set
/// to TRUE then the firmware will attempt to remove the offset of the sensor, moving it's base
/// reading back to 0. This value is how much offset is present after removing the offset. While the
/// offset my not be compeletely removed it may have been reduced to fall within the high and low
/// limits for acceptable offsets for the sensor. See <see cref="AnalogInputDASChannel" /> to find
/// these sensor specific values. When read from event attributes, a value of 0.0 might actually
/// mean null (i.e. was not measured).
/// </summary>
public short? FinalOffsetADC { get; set; }
public int? RemovedOffsetADC { get; set; }
public int? RemovedInternalOffsetADC { get; set; }
/// <summary>
/// FullScaleSignal to Noise ratio as a percentage. When read from event attributes, a value of 0.0 might actually
/// mean null (i.e. was not measured).
/// </summary>
public double? NoisePercentFullScale { get; set; }
public bool ShuntDeflectionFailed { get; set; }
public bool CalSignalCheckFailed { get; set; }
/// <summary>
/// If an emulated shunt test is performed the measured shunt deflection in mV detected
/// during the test will be here.
/// <see cref="DTS.DASLib.Service.DiagnosticsActions" />.PerformShuntCheck
/// When read from event attributes, a value of 0.0 might actually mean null
/// (i.e. was not measured).
/// </summary>
public double? MeasuredShuntDeflectionMv { get; set; }
public double? MeasuredCalSignalMv { get; set; }
public double? TargetCalSignalMv { get; set; }
public double? MeasuredDurationMS { get; set; }
public double? MeasuredDelayMS { get; set; }
public bool? SquibFirePassed { get; set; }
public bool? SquibDurationPassed { get; set; }
public bool? SquibDelayPassed { get; set; }
public double[] SquibFireCurrentData { get; set; }
public double[] SquibFireVoltageData { get; set; }
public double[] SquibFireTimeAxis { get; set; }
public double SquibThreshold { get; set; }
public double SquibVoltageScaler { get; set; }
public double SquibCurrentScaler { get; set; }
public double? TargetGain { get; set; }
public double? MeasuredGain { get; set; }
public double? QueriedGain { get; set; }
/// <summary>
/// If an emulated shunt test is performed the target shunt deflection in mV will be here.
/// CalibrateActions.PerformShuntCheck When read from event attributes, a value of 0.0 might actually
/// mean null (i.e. was not measured).
/// </summary>
public double? TargetShuntDeflectionMv { get; set; }
/// <summary>
/// If the bridge resistance of the sensor was measured, the measured resistance in
/// ohms will be here. <see cref="DiagnosticsActions.MeasureBridgeResistance" />
/// When read from event attributes, a value of 0.0 might actually mean null
/// (i.e. was not measured).
/// </summary>
public double? BridgeResistance { get; set; }
public short ZeroMVInADC { get; set; } = 0;
/// <summary>
/// WindowAverageADC is the average ADC over the averaging window specified for the channel
/// short.MinValue indicates an unitialized or invalid value
/// </summary>
public short WindowAverageADC { get; set; } = short.MinValue;
public bool DigitalInputActiveState { get; set; }
}
}

View File

@@ -0,0 +1,158 @@
using DTS.Common.Interface.DASFactory;
using DTS.Common.Interface.DASFactory.Diagnostics;
using DTS.Common.Utilities.Logging;
using System;
namespace DTS.DASLib.Service.Classes.Diagnostics
{
public static class DiagnosticsResultActions
{
/// <summary>
/// clears all diagnostics from all events and channels, and optionally clears from db
/// </summary>
/// <param name="unit"></param>
/// <param name="bClearDb"></param>
public static void ClearChannelDiagnosticsResults(IDASCommunication unit, bool bClearDb = true)
{
unit.ChannelDiagnosticsResults = new IDiagnosticResult[0];
unit.ChannelDiagnostics = new IDiagnosticActions[0];
if (!DASFactoryDb.DbWrapper.Connected || !bClearDb) { return; }
try
{
DASFactoryDb.Diagnostics.Diagnostics.ClearExistingDiagnosticsAllChannels(unit.RecordId);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
/// <summary>
/// sets the channel diagnostics, optionally writes to the db
/// </summary>
/// <param name="unit"></param>
/// <param name="results"></param>
/// <param name="setInDb"></param>
public static void SetChannelDiagnosticsResults(IDASCommunication unit, IDiagnosticResult[] results, bool setInDb)
{
unit.ChannelDiagnosticsResults = results;
if (!DASFactoryDb.DbWrapper.Connected || !setInDb) { return; }
try
{
foreach (var result in results)
{
var moduleNumber = unit.DASInfo.MapDASChannelNumber2ModuleArrayIndex(result.DASChannelNumber);
var channelIndex = unit.DASInfo.MapDASChannelNumber2ModuleChannelNumber(result.DASChannelNumber);
var channel = unit.ConfigData.Modules[moduleNumber].Channels[channelIndex];
if (channel is AnalogInputDASChannel aic)
{
if (aic.DigitalInputChannel)
{
InsertDiagnosticsResultDigital(unit, aic, result);
}
else
{
InsertDiagnosticsResultAnalog(unit, aic, result);
}
}
else if (channel is OutputSquibChannel squib)
{
InsertDiagnosticsResultsSquib(unit, squib, result);
}
}
}
catch (Exception ex) { APILogger.Log(ex); }
}
/// <summary>
/// writes a single digital result to the db
/// </summary>
/// <param name="das"></param>
/// <param name="aic"></param>
/// <param name="result"></param>
private static void InsertDiagnosticsResultDigital(IDASCommunication das, AnalogInputDASChannel aic,
IDiagnosticResult result)
{
try
{
DASFactoryDb.Diagnostics.Diagnostics.InsertDigitalDiagnosticResult(das.RecordId,
result.DASChannelNumber,
result.EventNumber,
result.DigitalInputActiveState);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
/// <summary>
/// writes a single analog result to the db
/// </summary>
/// <param name="das"></param>
/// <param name="aic"></param>
/// <param name="result"></param>
private static void InsertDiagnosticsResultAnalog(IDASCommunication das, AnalogInputDASChannel aic,
IDiagnosticResult result)
{
try
{
DASFactoryDb.Diagnostics.Diagnostics.InsertAnalogDiagnosticResult(
das.RecordId,
result.DASChannelNumber,
result.EventNumber,
result.ScalefactorMilliVoltsPerADC,
result.ExpectedExcitationMilliVolts,
result.MeasuredExcitationMilliVolts,
result.NegativeExcitation,
result.MeasuredOffsetMilliVolts,
result.MeasuredInternalOffsetMilliVolts,
result.AutoZeroPercentDeviation,
result.FinalOffsetADC,
result.RemovedOffsetADC,
result.RemovedInternalOffsetADC,
result.NoisePercentFullScale,
result.ShuntDeflectionFailed,
result.CalSignalCheckFailed,
result.MeasuredShuntDeflectionMv,
result.MeasuredCalSignalMv,
result.TargetCalSignalMv,
result.TargetGain,
result.MeasuredGain,
result.QueriedGain,
result.TargetShuntDeflectionMv,
result.BridgeResistance,
result.ZeroMVInADC,
result.WindowAverageADC);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
/// <summary>
/// writes a single squib diagnostic to the db
/// </summary>
/// <param name="das"></param>
/// <param name="squib"></param>
/// <param name="result"></param>
private static void InsertDiagnosticsResultsSquib(IDASCommunication das, OutputSquibChannel squib,
IDiagnosticResult result)
{
try
{
DASFactoryDb.Diagnostics.Diagnostics.InsertSquibDiagnosticResult(das.RecordId,
result.DASChannelNumber, result.EventNumber, result.SquibFireCurrentData,
result.SquibFireVoltageData, result.SquibFireTimeAxis, result.MeasuredDurationMS,
result.MeasuredDelayMS, result.SquibFirePassed, result.SquibDurationPassed, result.SquibDelayPassed,
result.SquibThreshold, result.SquibVoltageScaler, result.SquibCurrentScaler);
}
catch (Exception)
{
//for now just skip the logging
}
}
}
}

View File

@@ -0,0 +1,14 @@
using DTS.Common.Interface.DASFactory.Diagnostics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DTS.DASLib.Service.Classes.Diagnostics
{
public class OptimizationValues : IOptimizationValues
{
public float TransferSpeed { get; set; }
}
}