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

2302 lines
106 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using DTS.Common.DAS.Concepts;
using System.Data;
using DTS.Common.Enums;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
using DTS.Common.Interface.Sensors;
using DTS.Common.Enums.Sensors;
using DTS.Common.Classes.Sensors;
using System.Data.SqlClient;
using System.IO.Ports;
using DTS.Common.Interface.Tags;
using DTS.Common.Classes.DASFactory;
using DTS.Common;
using System.Globalization;
using DTS.Common.Constant;
namespace DTS.SensorDB
{
public class SensorData : SensorBase, IComparable<SensorData>, ISensorData, IUARTRecord
{
public new BridgeLeg BridgeLegMode
{
get => (BridgeLeg)base.BridgeLegMode;
set => base.BridgeLegMode = (short)value;
}
public new int TimesUsed
{
get => Convert.ToInt32(base.TimesUsed);
set => base.TimesUsed = value;
}
/// <summary>
/// sets the first use date of the sensor in the db to today
/// </summary>
/// <param name="sensor"></param>
public static void SetFirstUseDate(ISensorData sensor)
{
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.StoredProcedure;
sql.CommandText = "sp_SensorsAnalogFirstUseSet";
sql.Parameters.Add(new SqlParameter("@SensorId", SqlDbType.Int) { Value = sensor.DatabaseId });
sql.Parameters.Add(new SqlParameter("@FirstUseDate", SqlDbType.DateTime) { Value = DateTime.Today });
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);
sql.ExecuteNonQuery();
if (!DBNull.Value.Equals(errorNumber.Value))
{
if (Convert.ToInt32(errorNumber.Value) != 0)
{
throw new Exception(
$"Failed to set sensor first use date {sensor.SerialNumber}, {Convert.ToString(errorMessage.Value)}");
}
}
}
finally
{
sql.Connection.Dispose();
}
}
}
//FB 43246
public static bool IsInspectBeforeUseSet(SensorData data)
{
if (data.InspectBeforeUseCleared) { return false; }
SensorCalibrationList.Reload();
var sensorCalibrations = SensorCalibrationList.GetCalibrationsBySerialNumber(data);
return sensorCalibrations.Any(p => p.SensitivityInspection == SensitivityInspectionType.Required);
}
public static bool IsInspectBeforeUseSet(int sensorId)
{
var hr = DbOperations.SensorCalibrationsGet(sensorId, null, out var calRecords);
if (0 != hr || null == calRecords || !calRecords.Any())
{
return false;
}
return calRecords.Any(p => p.SensitivityInspection == SensitivityInspectionType.Required);
}
/// <summary>
/// sets the first use date of the sensor in the db to today
/// </summary>
/// <param name="sensor"></param>
public static void SetSensitivityInspection(ISensorData sensor, string clearedCalibrationNote = "")
{
int? sensorCalibrationId = null;
if (sensor.Calibration.SensitivityInspection == SensitivityInspectionType.Cleared)
{
SensorCalibrationList.Reload();
var sensorCalibrations = SensorCalibrationList.GetCalibrationsBySerialNumber((SensorData)sensor);
var sensorCalibration = sensorCalibrations.FirstOrDefault(p => p.SensitivityInspection == SensitivityInspectionType.Required);
if (sensorCalibration == null)
{
return;
}
sensorCalibrationId = sensorCalibration.CalibrationId;
}
else if (sensor.Calibration.SensitivityInspection == SensitivityInspectionType.Required)
{
sensorCalibrationId = sensor.Calibration.CalibrationId;
}
else
{
return;
}
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.StoredProcedure;
sql.CommandText = "sp_SensorCalibrationsSensitivityInspectionSet";
sql.Parameters.Add(new SqlParameter("@SensorId", SqlDbType.Int) { Value = sensor.DatabaseId });
sql.Parameters.Add(new SqlParameter("@SensorCalibrationId", SqlDbType.Int) {Value = sensorCalibrationId });
sql.Parameters.Add(new SqlParameter("@SensitivityInspection", SqlDbType.Int) { Value = sensor.Calibration.SensitivityInspection });
if (!string.IsNullOrEmpty(clearedCalibrationNote))
{
sql.Parameters.Add(new SqlParameter("@CalibrationNote", SqlDbType.NVarChar, 2048) { Value = clearedCalibrationNote });
}
else
{
sql.Parameters.Add(new SqlParameter("@CalibrationNote", SqlDbType.NVarChar, 2048) { Value = DBNull.Value});
}
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);
sql.ExecuteNonQuery();
if (!DBNull.Value.Equals(errorNumber.Value) && Convert.ToInt32(errorNumber.Value) != 0)
{
throw new Exception(
$"Failed to set SensitivityInspection to {sensor.Calibration.SensitivityInspection} for sensor {sensor.SerialNumber}, {Convert.ToString(errorMessage.Value)}");
}
}
finally
{
sql.Connection.Dispose();
}
}
}
public bool IsAnalog()
{
return !IsDigitalInput() && !IsDigitalOutput() && !IsSquib() && !IsUart() && !IsStreamInput() && !IsStreamOutput() && !IsThermocoupler() && !IsCan();
}
/// <summary>
/// initial offset information is stored in a sensor calibration at least in terms of possible settings for the sensor
/// HOWEVER, the offset to use is stored here for convenience, this is the result of group or test parameters
///
/// </summary>
public InitialOffset InitialOffset { get; set; } = null;
public ISensorCalibration GetLatestCalibration()
{
return SensorCalibrationList.GetLatestCalibrationBySerialNumber(this);
}
public ISensorCalibration NewEmbeddedSC(string units)
{
return SensorCalibrationList.NewEmbeddedSC(units);
}
public void Initialize(ISquibSettingDefaults defaults)
{
SquibFireDelayMS = defaults.FireDelayMS;
SquibFireDurationMS = defaults.FireDurationMS;
SquibFireMode = defaults.FireModeDefault;
LimitSquibFireDuration = defaults.LimitDurationDefault;
SquibOutputCurrent = defaults.OutputCurrentDefault;
SquibToleranceHigh = defaults.ToleranceHighDefault;
SquibToleranceLow = defaults.ToleranceLowDefault;
}
public void Initialize(IDigitalOutDefaults defaults)
{
DigitalOutputDelayMS = defaults.DelayMS;
DigitalOutputDurationMS = defaults.DurationMS;
DigitalOutputLimitDuration = defaults.LimitDuration;
DigitalOutputMode = defaults.OutputMode;
}
public void Initialize(IUartSettingDefaults defaults)
{
UartBaudRate = defaults.BaudRate;
UartDataBits = defaults.DataBits;
UartStopBits = defaults.StopBits;
UartParity = defaults.Parity;
//FB 30486 Hardcode FlowControl to NONE for UART sensor type
UartDataFormat = defaults.DataFormat;
}
public void Initialize(IStreamOutputSettingDefaults defaults)
{
StreamOutUDPProfile = defaults.Profile;
StreamOutUDPAddress = defaults.UDPAddress;
StreamOutUDPTimeChannelId = defaults.TimeChannelId;
StreamOutUDPDataChannelId = defaults.DataChannelId;
StreamOutUDPTmNSConfig = defaults.TmNSConfig;
StreamOutIRIGTimeDataPacketIntervalMs = defaults.IRIGTimeDataPacketIntervalMs;
StreamOutTMATSIntervalMs = StreamOutputRecord.DEFAULT_TMATS_INTERVAL_MS;
}
public void Initialize(ICanSettingDefaults defaults)
{
CanIsFD = defaults.IsFD;
CanArbBaseBitrate = defaults.ArbBaseBitrate;
CanArbBaseSJW = defaults.ArbBaseSJW;
CanDataBitrate = defaults.DataBitrate;
CanDataSJW = defaults.DataSJW;
CanFileType = defaults.FileType;
}
public void Initialize(IStreamInputSettingDefaults defaults)
{
StreamInUDPAddress = defaults.UDPAddress;
}
public void InitializeTag(SensorConstants.BridgeType bridgeType)
{
SetTags(bridgeType == SensorConstants.BridgeType.DigitalInput
? new string[] { "Digital In" }
: new string[] { "" }, DbOperations.GetSQLCommand, DbOperations.TagsGet,
DbOperations.TagsGetId, DbOperations.TagsInsert);
}
public int DatabaseId
{
get => Id;
set
{
Id = value;
OnPropertyChanged("DatabaseId");
}
}
public short GetSensorType()
{
if (IsSquib())
{
return 3;
}
if (IsDigitalInput())
{
return 1;
}
if (IsDigitalOutput())
{
return 2;
}
if (IsUart())
{
return 4;
}
return 0;
}
public int SensorCalWarningPeriodDays { get; set; }
public override TagTypes TagType => TagTypes.Sensors;
/// <summary>
/// gets the offset in terms of EU regardless of form
/// </summary>
/// <param name="sc">the calibration to calculate with
/// this is important as EU@mV is connected to a sensitivity value
/// </param>
/// <param name="voltage"></param>
/// <param name="io"></param>
/// <returns></returns>
public static double GetInitialEUValue(ISensorCalibration sc, ExcitationVoltageOptions.ExcitationVoltageOption voltage, InitialOffset io)
{
switch (io.Form)
{
case InitialOffsetTypes.EU: return io.EU;
case InitialOffsetTypes.None: return 0D;
case InitialOffsetTypes.EUAtMV:
{
if (sc.NonLinear)
{
return 0D;
}
foreach (var r in sc.Records.Records)
{
if (r.Excitation != voltage) continue;
//changed per takashi
if (sc.IsProportional)
{
return io.EU - (io.MV / r.Sensitivity) / Test.Module.Channel.Sensor.GetExcitationVoltageMagnitudeFromEnum(voltage);
}
return io.EU - io.MV / r.Sensitivity;
}
}
throw new NullReferenceException("No calibration record found for " + voltage);
default: throw new NotSupportedException("InitialOffset::GetInitialEUValue unsupported form: " + io.Form);
}
}
public bool IsTestSpecificDigitalOutput
{
get => SensorConstants.IsTestSpecificDigitalOut(SerialNumber);
set
{
if (value)
{
SerialNumber = $"{SensorConstants.TEST_SPECIFIC_DOUT}{Guid.NewGuid()}";
}
}
}
public bool IsTestSpecificSquib
{
get => SensorConstants.IsTestSpecificSquib(SerialNumber);
set
{
if (value)
{
SerialNumber = $"{SensorConstants.TEST_SPECIFIC_SQUIB}{Guid.NewGuid()}";
}
}
}
/// <summary>
/// returns true if the sensor is a test specific digital input
/// a digital input only created within a specific test
/// </summary>
public bool IsTestSpecificDigitalIn
{
get => SensorConstants.IsTestSpecificDigitalIn(SerialNumber);
set
{
if (value)
{
SerialNumber = $"{SensorConstants.TEST_SPECIFIC_DIN}{Guid.NewGuid()}";
}
}
}
/// <summary>
/// returns true if the channel is test specific embedded
///</summary>
public bool IsTestSpecificEmbedded
{
get => SensorConstants.IsTestSpecificEmbedded(SerialNumber);
set
{
if (value)
{
SerialNumber = $"{SensorConstants.TEST_SPECIFIC_EMB}{Guid.NewGuid()}";
}
}
}
/// <summary>
/// returns true if the channel is a test specific thermocouple
/// </summary>
public bool IsTestSpecificThermo
{
get => SensorConstants.IsTestSpecificThermoCouple(SerialNumber);
}
public bool IsTestSpecificEmbeddedClock
{
get => SensorConstants.IsTestSpecificEmbeddedClock(SerialNumber);
set
{
if (value)
{
SerialNumber = $"{SensorConstants.TEST_SPECIFIC_EMB_CLK}{Guid.NewGuid()}";
}
}
}
public bool IsTestSpecificUart
{
get => SensorConstants.IsTestSpecificUart(SerialNumber);
set
{
if (value)
{
SerialNumber = $"{SensorConstants.TEST_SPECIFIC_UART}{Guid.NewGuid()}";
}
}
}
public bool IsTestSpecificStreamInput
{
get => SensorConstants.IsTestSpecificStreamIn(SerialNumber);
set
{
if (value)
{
SerialNumber = $"{SensorConstants.TEST_SPECIFIC_STREAM_IN}{Guid.NewGuid()}";
}
}
}
public bool IsTestSpecificStreamOutput
{
get => SensorConstants.IsTestSpecificStreamOut(SerialNumber);
set
{
if (value)
{
SerialNumber = $"{SensorConstants.TEST_SPECIFIC_STREAM_OUT}{Guid.NewGuid()}";
}
}
}
public bool IsTestSpecificCan
{
get => SensorConstants.IsTestSpecificCAN(SerialNumber);
set
{
if (value)
{
SerialNumber = $"{SensorConstants.TEST_SPECIFIC_CAN}{Guid.NewGuid()}";
}
}
}
/// <summary>
/// At one time all the different DelayMS were using one underlying property for storage, _delayMS.
/// Now, the individual SquibFireDelayMS, etc. are defined because we don't want controls that are sharing to limit each other.
/// </summary>
public double DelayMS
{
get => _delayMS;
set => _delayMS = value;
}
public const double MINIMUM_DIGITALOUTPUT_DELAY_MS = 0D;
public const double MAXIMUM_DIGITALOUTPUT_DELAY_MS = 99000D;
private double _digitalOutputDelayMS;
public double DigitalOutputDelayMS
{
get => _digitalOutputDelayMS;
set
{
var d = value;
if (d < MINIMUM_DIGITALOUTPUT_DELAY_MS)
{
d = MINIMUM_DIGITALOUTPUT_DELAY_MS;
}
else if (d > MAXIMUM_DIGITALOUTPUT_DELAY_MS)
{
d = MAXIMUM_DIGITALOUTPUT_DELAY_MS;
}
SetProperty(ref _digitalOutputDelayMS, d, "DigitalOutputDelayMS");
}
}
/// <summary>
/// At one time all the different DurationMS were using one underlying property for storage, _durationMS.
/// Now, the individual SquibFireDurationMS, etc. are defined because we don't want controls that are sharing to limit each other.
/// </summary>
public double DurationMS
{
get => _durationMS;
set => SetProperty(ref _durationMS, value, "DurationMS");
}
private double _digitalOutputDurationMS = 10D;
public double DigitalOutputDurationMS
{
get => _digitalOutputDurationMS;
set => SetProperty(ref _digitalOutputDurationMS, value, "DigitalOutputDurationMS");
}
private DigitalOutputModes _digitalOutputMode = DigitalOutputModes.FVLH;
public DigitalOutputModes DigitalOutputMode
{
get => _digitalOutputMode;
set => SetProperty(ref _digitalOutputMode, value, "DigitalOutputMode");
}
public bool DigitalOutputLimitDuration
{
get => _limitDuration;
set => SetProperty(ref _limitDuration, value, "LimitDuration");
}
private double _delayMS;
public double SquibFireDelayMS
{
get => _delayMS;
set => SetProperty(ref _delayMS, value, "SquibFireDelayMS");
}
private double _durationMS = 10D;
public double SquibFireDurationMS
{
get => _durationMS;
set => SetProperty(ref _durationMS, value, "SquibFireDurationMS");
}
/// <summary>
/// right now all the Limit Duration mechanisms using the same underlying property for storage (_limitDuration), however
/// the public access methods (LimitSquibDuration, etc) exist in case we separate them out in the future
/// </summary>
public bool LimitDuration
{
get => _limitDuration;
set => SetProperty(ref _limitDuration, value, "LimitDuration");
}
private bool _limitDuration = true;
public bool LimitSquibFireDuration
{
get => _limitDuration;
set => SetProperty(ref _limitDuration, value, "LimitSquibFireDuration");
}
private bool _defineDelayInTest = false;
public bool DefineDelayInTest
{
get => _defineDelayInTest;
set => SetProperty(ref _defineDelayInTest, value, "DefineDelayInTest");
}
private double _squibToleranceLow = 1D;
public double SquibToleranceLow
{
get => _squibToleranceLow;
set => SetProperty(ref _squibToleranceLow, value, "SquibToleranceLow");
}
private double _squibToleranceHigh = 8D;
public double SquibToleranceHigh
{
get => _squibToleranceHigh;
set => SetProperty(ref _squibToleranceHigh, value, "SquibToleranceHigh");
}
private SquibMeasurementType _squibMeasurementType = SquibMeasurementType.VOLTAGE;
public SquibMeasurementType SquibMeasurementType
{
get => _squibMeasurementType;
set => SetProperty(ref _squibMeasurementType, value, "SquibMeasurementType");
}
private double _squibOutputCurrent = 1.5D;
public double SquibOutputCurrent
{
get => _squibOutputCurrent;
set => SetProperty(ref _squibOutputCurrent, value, "SquibOutputCurrent");
}
public new string DisplayUnit
{
get
{
if (IsSquib())
{
switch (SquibMeasurementType)
{
case SquibMeasurementType.CURRENT:
return "A";
default:
return "V";
}
}
if (null == Calibration || 0 == Calibration.Records.Records.Length) { return ""; }
return Calibration.Records.Records[0].EngineeringUnits; //6194 disable display units for the short term
}
//6194 disable display units for the short term
set { }
}
public bool BypassCurrentFilter => false;
public bool BypassVoltageFilter => false;
private SquibFireMode _squibFireMode = SquibFireMode.NONE;
public SquibFireMode SquibFireMode
{
get => _squibFireMode;
set => SetProperty(ref _squibFireMode, value, "SquibFireMode");
}
/// <summary>
/// the input mode for this setting
/// </summary>
protected DigitalInputModes _inputMode = DigitalInputModes.CCNO;
/// <summary>
/// the scaler is a bit different than an ordinary scaler, so the name here is inaccurate, however the idea is
/// that we allow the user to transform collected data, primarly by allowing them to define the 0,1 value of the digital output
/// </summary>
protected DigitalInputScaleMultiplier _digitalInputScaleMultiplier = new DigitalInputScaleMultiplier();
/// <summary>
/// the setting name allows us to refer to different settings and allow it to be more easily included in test setups and channel setups
/// </summary>
public string SettingName
{
get => SerialNumber;
set
{
SerialNumber = value;
OnPropertyChanged("SettingName");
}
}
public DigitalInputModes InputMode
{
get => _inputMode;
set => SetProperty(ref _inputMode, value, "InputMode");
}
public DigitalInputScaleMultiplier ScaleMultiplier
{
get => _digitalInputScaleMultiplier;
set => SetProperty(ref _digitalInputScaleMultiplier, value, "ScaleMultiplier");
}
protected uint _baudRate = DTS.Common.Constant.EmbeddedSensors.BAUD_RATE_DEFAULT;
public uint UartBaudRate
{
get => _baudRate;
set => SetProperty(ref _baudRate, value, "UartBaudRate");
}
public const uint MINIMUM_UART_DATABITS = 5;
public const uint MAXIMUM_UART_DATABITS = 9;
protected uint _dataBits = UARTRecord.UART_DATABITS_DEFAULT;
public uint UartDataBits
{
get => _dataBits;
set => SetProperty(ref _dataBits, value, "UartDataBits");
}
protected StopBits _stopBits = StopBits.None;
public StopBits UartStopBits
{
get => _stopBits;
set => SetProperty(ref _stopBits, value, "UartStopBits");
}
protected Parity _parity = Parity.None;
public Parity UartParity
{
get => _parity;
set => SetProperty(ref _parity, value, "UartParity");
}
protected Handshake _flowControl = Handshake.None;
public Handshake UartFlowControl
{
//FB 30486 Hardcode FlowControl to NONE for UART sensor type
get => Handshake.None;
}
protected UartDataFormat _dataFormat = UARTRecord.UART_DATAFORMAT_DEFAULT;
public UartDataFormat UartDataFormat
{
get => _dataFormat;
set => SetProperty(ref _dataFormat, value, "UartDataFormat");
}
protected bool _canIsFd = EmbeddedSensors.CANISFD_DEFAULT;
public bool CanIsFD
{
get => _canIsFd;
set => SetProperty(ref _canIsFd, value, "CanIsFD");
}
protected int _canArbBaseBitrate = EmbeddedSensors.CANFD_ARB_BASE_BITRATE_DEFAULT;
public int CanArbBaseBitrate
{
get => _canArbBaseBitrate;
set => SetProperty(ref _canArbBaseBitrate, value, "CanArbBaseBitrate");
}
protected int _canArbBaseSJW = EmbeddedSensors.CANFD_1000000_ARB_BASE_SJW_MAX;
public int CanArbBaseSJW
{
get => _canArbBaseSJW;
set => SetProperty(ref _canArbBaseSJW, value, "CanArbBaseSJW");
}
protected int _canDataBitrate = EmbeddedSensors.DATA_BITRATE_DEFAULT;
public int CanDataBitrate
{
get => _canDataBitrate;
set => SetProperty(ref _canDataBitrate, value, "CanDataBitrate");
}
protected int _canDataSJW = EmbeddedSensors.DATA_SJW_DEFAULT;
public int CanDataSJW
{
get => _canDataSJW;
set => SetProperty(ref _canDataSJW, value, "CanDataSJW");
}
protected string _canFileType = EmbeddedSensors.FILETYPE_DEFAULT;
public string CanFileType
{
get => _canFileType;
set => SetProperty(ref _canFileType, value, "CanFileType");
}
protected UDPStreamProfile _outudpProfile = StreamOutputRecord.DEFAULT_UDP_PROFILE;
public UDPStreamProfile StreamOutUDPProfile
{
get => _outudpProfile;
set => SetProperty(ref _outudpProfile, value, "StreamOutUDPProfile");
}
protected string _outudpAddress = StreamOutputRecord.DEFAULT_UDP_ADDRESS;
public string StreamOutUDPAddress
{
get => _outudpAddress;
set => SetProperty(ref _outudpAddress, value, "StreamOutUDPAddress");
}
protected string _inudpAddress = StreamInputRecord.DEFAULT_UDP_ADDRESS;
public string StreamInUDPAddress
{
get => _inudpAddress;
set => SetProperty(ref _inudpAddress, value, "StreamInUDPAddress");
}
protected ushort _udpTimeChannelId = StreamOutputRecord.DEFAULT_UDP_TIME_CHANNEL_ID;
public ushort StreamOutUDPTimeChannelId
{
get => _udpTimeChannelId;
set => SetProperty(ref _udpTimeChannelId, value, "StreamOutUDPTimeChannelId");
}
protected ushort _udpDataChannelId = StreamOutputRecord.DEFAULT_UDP_DATA_CHANNEL_ID;
public ushort StreamOutUDPDataChannelId
{
get => _udpDataChannelId;
set => SetProperty(ref _udpDataChannelId, value, "StreamOutUDPDataChannelId");
}
protected string _udpTmNSConfig = StreamOutputRecord.DEFAULT_UDPTMNS_CONFIG;
public string StreamOutUDPTmNSConfig
{
get => _udpTmNSConfig;
set => SetProperty(ref _udpTmNSConfig, value, "StreamOutUDPTmNSConfig");
}
/// <summary>
/// the TMNS sub frame id for output streaming
/// </summary>
public uint TMNS_SubFrameId
{
get
{
var tmns = new TMNSConfig(StreamOutUDPTmNSConfig);
return tmns.TMNS_PCMSubFrameId;
}
set
{
var tmns = new TMNSConfig(StreamOutUDPTmNSConfig);
tmns.TMNS_PCMSubFrameId = value;
StreamOutUDPTmNSConfig = tmns.ToCSVString();
OnPropertyChanged("TMNS_SubFrameId");
}
}
/// <summary>
/// the TMNS message id for output streaming
/// </summary>
public uint TMNS_MsgId
{
get
{
var tmns = new TMNSConfig(StreamOutUDPTmNSConfig);
return tmns.TMNS_MsgId;
}
set
{
var tmns = new TMNSConfig(StreamOutUDPTmNSConfig);
tmns.TMNS_MsgId = value;
StreamOutUDPTmNSConfig = tmns.ToCSVString();
OnPropertyChanged("TMNS_MsgId");
}
}
/// <summary>
/// the tMNS PCM minor per major for output streaming
/// </summary>
public uint TMNS_MinorPerMajor
{
get
{
var tmns = new TMNSConfig(StreamOutUDPTmNSConfig);
return tmns.TMNS_PCMMinorPerMajor;
}
set
{
var tmns = new TMNSConfig(StreamOutUDPTmNSConfig);
tmns.TMNS_PCMMinorPerMajor = value;
StreamOutUDPTmNSConfig = tmns.ToCSVString();
OnPropertyChanged("TMNS_MinorPerMajor");
}
}
/// <summary>
/// TMNS TMATs port for output streaming
/// </summary>
public uint TMNS_TMATSPort
{
get
{
var tmns = new TMNSConfig(StreamOutUDPTmNSConfig);
return tmns.TMNS_TMATSPortNumber;
}
set
{
var tmns = new TMNSConfig(StreamOutUDPTmNSConfig);
tmns.TMNS_TMATSPortNumber = value;
StreamOutUDPTmNSConfig = tmns.ToCSVString();
OnPropertyChanged("TMNS_TMATSPort");
}
}
/// <summary>
/// IENA source port for output streaming
/// </summary>
public uint IENA_SourcePort
{
get
{
var tmns = new TMNSConfig(StreamOutUDPTmNSConfig);
return tmns.IENAUDP_PortNumber;
}
set
{
var tmns = new TMNSConfig(StreamOutUDPTmNSConfig);
tmns.IENAUDP_PortNumber = value;
StreamOutUDPTmNSConfig = tmns.ToCSVString();
OnPropertyChanged("IENA_SourcePort");
}
}
/// <summary>
/// IENA key for output streaming
/// </summary>
public ushort IENA_Key
{
get
{
return StreamOutUDPDataChannelId;
}
set
{
StreamOutUDPDataChannelId = value;
OnPropertyChanged("IENA_Key");
}
}
protected ushort _irigTimeDataPacketIntervalMs = StreamOutputRecord.DEFAULT_IRIG_TIME_DATA_PACKET_INTERVAL_MS;
public ushort StreamOutIRIGTimeDataPacketIntervalMs
{
get => _irigTimeDataPacketIntervalMs;
set => SetProperty(ref _irigTimeDataPacketIntervalMs, value, "StreamOutIRIGTimeDataPacketIntervalMs");
}
protected ushort _streamOutTMATSIntervalMs = StreamOutputRecord.DEFAULT_TMATS_INTERVAL_MS;
/// <summary>
/// Time in ms between sending out tmats information while streaming
/// http://manuscript.dts.local/f/cases/29987/Add-CG-DP-TMATS-interval-UI-support
/// </summary>
public ushort StreamOutTMATSIntervalMs
{
get => _streamOutTMATSIntervalMs;
set => SetProperty(ref _streamOutTMATSIntervalMs, value, "StreamOutTMATSIntervalMs");
}
public SensorData(SensorData copy)
{
if (null == copy) { copy = new SensorData(); }
DatabaseId = copy.DatabaseId;
_digitalOutputMode = copy._digitalOutputMode;
_diUnits = copy._diUnits;
_inputMode = copy._inputMode;
SquibMeasurementType = copy.SquibMeasurementType;
_digitalInputScaleMultiplier = new DigitalInputScaleMultiplier(copy._digitalInputScaleMultiplier);
_delayMS = copy._delayMS;
_digitalOutputDelayMS = copy._digitalOutputDelayMS;
_durationMS = copy._durationMS;
_digitalOutputDurationMS = copy._digitalOutputDurationMS;
_limitDuration = copy._limitDuration;
_defineDelayInTest = copy._defineDelayInTest;
_squibToleranceHigh = copy._squibToleranceHigh;
_squibToleranceLow = copy._squibToleranceLow;
_squibFireMode = copy._squibFireMode;
_squibOutputCurrent = copy._squibOutputCurrent;
_baudRate = copy._baudRate;
_dataBits = copy._dataBits;
_stopBits = copy._stopBits;
_parity = copy._parity;
_flowControl = copy._flowControl;
_dataFormat = copy._dataFormat;
_inudpAddress = copy._inudpAddress;
_outudpProfile = copy._outudpProfile;
_outudpAddress = copy._outudpAddress;
_udpTimeChannelId = copy._udpTimeChannelId;
_udpDataChannelId = copy._udpDataChannelId;
_udpTmNSConfig = copy._udpTmNSConfig;
_irigTimeDataPacketIntervalMs = copy._irigTimeDataPacketIntervalMs;
TagsBlobBytes = copy.TagsBlobBytes;
DoNotUse = copy.DoNotUse;
Broken = copy.Broken;
SensitivityTolerancePercent = copy.SensitivityTolerancePercent;
if (null != copy.Calibration)
{
Calibration = new SensorCalibration((SensorCalibration)copy.Calibration);
}
try
{
AssemblyName = copy.AssemblyName;
AxisNumber = copy.AxisNumber;
BridgeLegMode = copy.BridgeLegMode;
BridgeResistance = copy.BridgeResistance;
Bridge = copy.Bridge;
ByPassFilter = copy.ByPassFilter;
CheckCalibrationSignal = copy.CheckCalibrationSignal;
CalInterval = copy.CalInterval;
Capacity = copy.Capacity;
CheckOffset = copy.CheckOffset;
Comment = copy.Comment;
CouplingMode = copy.CouplingMode;
Created = copy.Created;
ExternalShuntResistance = copy.ExternalShuntResistance;
Filter = copy.Filter;
//FB 13120 set filter class
FilterClass = copy.FilterClass;
EID = copy.EID;
InternalShuntResistance = copy.InternalShuntResistance;
Invert = copy.Invert;
ISOCode = copy.ISOCode;
ISOChannelName = copy.ISOChannelName;
UserCode = copy.UserCode;
UserChannelName = copy.UserChannelName;
LastModified = copy.LastModified;
_localOnly = copy.LocalOnly;
Manufacturer = copy.Manufacturer;
DisplayUnit = copy.DisplayUnit;
Model = copy.Model;
LastUpdatedBy = copy.LastUpdatedBy;
NumberOfAxes = copy.NumberOfAxes;
OffsetToleranceHigh = copy.OffsetToleranceHigh;
OffsetToleranceLow = copy.OffsetToleranceLow;
RangeMedium = copy.RangeMedium;
RangeHigh = copy.RangeHigh;
RangeLow = copy.RangeLow;
SensorCategory = copy.SensorCategory;
SerialNumber = copy.SerialNumber;
Shunt = copy.Shunt;
Status = copy.Status;
TimesUsed = copy.TimesUsed;
UniPolar = copy.UniPolar;
UserSerialNumber = copy.UserSerialNumber;
UserValue1 = copy.UserValue1;
UserValue2 = copy.UserValue2;
UserValue3 = copy.UserValue3;
DiagnosticsMode = copy.DiagnosticsMode;
Version = copy.Version;
SetSupportedExcitationFromString(copy.GetSerializedSupportedExcitation());
TagsBlobBytes = copy.TagsBlobBytes;
DoNotUse = copy.DoNotUse;
Broken = copy.Broken;
//FB 43046
SensitivityTolerancePercent = copy.SensitivityTolerancePercent;
DontAllowDataCollectionIfOverused = copy.DontAllowDataCollectionIfOverused;
UsageCount = copy.UsageCount;
MaximumUsage = copy.MaximumUsage;
}
catch (Exception ex)
{
APILogger.Log(ex);
}
FilterClassIso = copy.FilterClassIso;
MeasureExcitation = copy.MeasureExcitation;
MeasureNoise = copy.MeasureNoise;
LatestCalibrationId = copy.LatestCalibrationId;
FirstUseDate = copy.FirstUseDate;
}
/// <summary>
/// returns the calibration due date for sensor given a sensor calibration
/// 13065 Sensor "First Use" Date
/// </summary>
public DateTime GetDueDate(ISensorCalibration sc)
{
if (null == sc) { return DateTime.MinValue; }
if (SensorConstants.UseSensorFirstUseDate)
{
if (sc.CalibrationId != null && sc.CalibrationId == LatestCalibrationId)
{
if (null == FirstUseDate)
{
return DateTime.Today.AddDays(CalInterval);
}
return ((DateTime)FirstUseDate).AddDays(CalInterval);
}
}
return sc.CalibrationDate.AddDays(CalInterval);
}
public override string ToString()
{
if (IsTestSpecificDigitalOutput)
{
return StringResources.Value_NA;
}
if (IsTestSpecificSquib)
{
return StringResources.Value_NA;
}
if (IsTestSpecificDigitalIn)
{
return StringResources.Value_NA;
}
return $"{GetSerialNumberWithAxis(StringResources.SensorAxis)} ({Comment})";
}
/// <summary>
/// Returns comment string. Returns serial number with axis if comment is not present.
/// </summary>
/// <returns></returns>
//FB 5960 New channels "Channel Name" in Non-ISO Group editor should only include Channel Name
public string ToDisplayString()
{
return string.IsNullOrEmpty(Comment) ? GetSerialNumberWithAxis(StringResources.SensorAxis) : Comment;
}
private void CommonInit(IReadOnlyDictionary<string, SensorCalibration> calLookup = null)
{
try
{
if (SensorConstants.UseSensorFirstUseDate)
{
if (null != calLookup && calLookup.ContainsKey(SerialNumber))
{
LatestCalibrationId = calLookup[SerialNumber].CalibrationId;
}
else
{
LatestCalibrationId = GetLatestCalibrationId(DatabaseId);
}
}
InitialOffset = new InitialOffset(); //Set the default
if (SensorConstants.IsTestSpecificEmbedded(SerialNumber) || SensorConstants.IsTestSpecificThermoCouple(SerialNumber))
{
BridgeResistance = -1;
Shunt = ShuntMode.None;
}
}
catch (Exception ex)
{
APILogger.Log("Failed to process: ", ex);
}
}
public SensorData(IAnalogDbRecord record, IReadOnlyDictionary<string, SensorCalibration> calLookup = null)
: base(record)
{
CommonInit(calLookup);
}
//added an option parameter to prevent querying cals one by one by passing in a dictionary
//17991 calspan speed ups for opening a test setup
public SensorData(IDataReader reader, int actualDbVersion, IReadOnlyDictionary<string, SensorCalibration> calLookup = null)
: base(reader, actualDbVersion)
{
CommonInit(calLookup);
}
public static int GetLatestCalibrationId(int sensorId)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = $"SELECT TOP (1) [SensorCalibrationId] FROM [{RunTestVariables.DbName}].[dbo].[SensorCalibrations] WHERE [SensorId]=@1 ORDER BY [CalibrationDate] DESC, [ModifyDate] DESC";
cmd.Parameters.Add(new SqlParameter("@1", SqlDbType.Int)
{ Value = sensorId });
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
return Convert.ToInt32(reader["SensorCalibrationId"]);
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
finally
{
cmd.Connection.Dispose();
}
return -1;
}
}
public void ReadXML(System.Xml.XmlElement root)
{
foreach (var node in root.ChildNodes)
{
if (node is System.Xml.XmlElement) { ProcessXMLElement(node as System.Xml.XmlElement); }
}
}
private void ProcessXMLElement(System.Xml.XmlElement node)
{
if (Enum.TryParse(node.Name, out AllSensorDataFields field))
{
switch (field)
{
case AllSensorDataFields.AxisNumber: AxisNumber = Convert.ToInt16(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.BridgeLegMode: BridgeLegMode = (BridgeLeg)Enum.Parse(typeof(BridgeLeg), node.InnerText); break;
case AllSensorDataFields.BridgeResistance: BridgeResistance = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.BridgeType: Bridge = (SensorConstants.BridgeType)Enum.Parse(typeof(SensorConstants.BridgeType), node.InnerText); break;
case AllSensorDataFields.BypassFilter: ByPassFilter = Convert.ToBoolean(node.InnerText); break;
case AllSensorDataFields.CalibrationSignal: CheckCalibrationSignal = Convert.ToBoolean(node.InnerText); break;
case AllSensorDataFields.CalInterval: CalInterval = Convert.ToInt32(node.InnerText); break;
case AllSensorDataFields.InitialEU: break;
case AllSensorDataFields.Capacity: Capacity = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.CheckOffset: CheckOffset = Convert.ToBoolean(node.InnerText); break;
case AllSensorDataFields.Comment: Comment = node.InnerText; break;
case AllSensorDataFields.CouplingMode: CouplingMode = (SensorConstants.CouplingModes)Enum.Parse(typeof(SensorConstants.CouplingModes), node.InnerText); break;
case AllSensorDataFields.Created: Created = DateTime.Parse(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.ExternalShuntResistance: ExternalShuntResistance = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.FilterClass: Filter = new FilterClass(node.InnerText); break;
case AllSensorDataFields.Id: EID = node.InnerText; break;
case AllSensorDataFields.InternalShuntResistance: InternalShuntResistance = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.Invert: Invert = Convert.ToBoolean(node.InnerText); break;
case AllSensorDataFields.IsoCode: ISOCode = BuildIsoCodeFromFilter(node.InnerText, Filter.FClass); break;
case AllSensorDataFields.IsoChannelName: ISOChannelName = node.InnerText; break;
case AllSensorDataFields.UserCode: UserCode = node.InnerText; break;
case AllSensorDataFields.UserChannelName: UserChannelName = node.InnerText; break;
case AllSensorDataFields.LastModified: LastModified = DateTime.Parse(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.LocalOnly: _localOnly = Convert.ToBoolean(node.InnerText); break;
case AllSensorDataFields.Manufacturer: Manufacturer = node.InnerText; break;
case AllSensorDataFields.MeasurementUnit: DisplayUnit = node.InnerText; break;
case AllSensorDataFields.Model: Model = node.InnerText; break;
case AllSensorDataFields.ModifiedBy: LastUpdatedBy = node.InnerText; break;
case AllSensorDataFields.NumberOfAxes: NumberOfAxes = Convert.ToInt16(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.OffsetToleranceHigh: OffsetToleranceHigh = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.OffsetToleranceLow: OffsetToleranceLow = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.RangeAve: RangeMedium = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.RangeHigh: RangeHigh = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.RangeLow: RangeLow = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.SensorCategory: SensorCategory = Convert.ToInt32(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.SerialNumber: SerialNumber = node.InnerText; break;
case AllSensorDataFields.Shunt: Shunt = (ShuntMode)Enum.Parse(typeof(ShuntMode), node.InnerText); break;
case AllSensorDataFields.Status: Status = (SensorStatus)Enum.Parse(typeof(SensorStatus), node.InnerText); break;
case AllSensorDataFields.SupportedExcitation:
{
var tokens = node.InnerText.Split(new[] { System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator }, StringSplitOptions.None);
SupportedExcitation = (from tok in tokens where !string.IsNullOrWhiteSpace(tok) select (ExcitationVoltageOptions.ExcitationVoltageOption)Enum.Parse(typeof(ExcitationVoltageOptions.ExcitationVoltageOption), tok)).ToArray();
}
break;
case AllSensorDataFields.TimesUsed: TimesUsed = Convert.ToInt32(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.UniPolar: UniPolar = Convert.ToBoolean(node.InnerText); break;
case AllSensorDataFields.UserSerialNumber: UserSerialNumber = node.InnerText; break;
case AllSensorDataFields.DiagnosticsMode: DiagnosticsMode = Convert.ToBoolean(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.UserValue1: UserValue1 = node.InnerText; break;
case AllSensorDataFields.UserValue2: UserValue2 = node.InnerText; break;
case AllSensorDataFields.UserValue3: UserValue3 = node.InnerText; break;
case AllSensorDataFields.Version: Version = Convert.ToInt32(node.InnerText, System.Globalization.CultureInfo.InvariantCulture); break;
case AllSensorDataFields.SquibSquibToleranceLow:
SquibToleranceLow = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture);
break;
case AllSensorDataFields.SquibSquibToleranceHigh:
SquibToleranceHigh = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture);
break;
case AllSensorDataFields.SquibSquibOutputCurrent:
SquibOutputCurrent = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture);
break;
case AllSensorDataFields.SquibMeasurementType:
{
if (Enum.TryParse(node.InnerText, out SquibMeasurementType mType)) { SquibMeasurementType = mType; }
}
break;
case AllSensorDataFields.SquibLimitDuration:
LimitSquibFireDuration = Convert.ToBoolean(node.InnerText);
break;
case AllSensorDataFields.SquibISOCode: ISOCode = node.InnerText; break;
case AllSensorDataFields.SquibFireMode:
{
if (Enum.TryParse(node.InnerText, out SquibFireMode fireMode))
{
SquibFireMode = fireMode;
}
}
break;
case AllSensorDataFields.SquibDurationMS:
SquibFireDurationMS = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture);
break;
case AllSensorDataFields.SquibDescription:
//SerialNumber
break;
case AllSensorDataFields.SquibDelayMS:
var fireDelayMs = Convert.ToDouble(node.InnerText, System.Globalization.CultureInfo.InvariantCulture);
// FB14777 Update the logic since -1 is a valid delay now
if (DASLib.Service.OutputSquibChannel.DEFAULT_DEFINEINTEST_FIRE_DELAY_FLAG == fireDelayMs)
{
fireDelayMs = DASLib.Service.OutputSquibChannel.DEFAULT_DEFINEINTEST_FIRE_DELAY_FLAG;
}
// FB 5827; Saving squibs with invalid delay settings
else if (DASLib.Service.OutputSquibChannel.DEFAULT_MIN_FIRE_DELAY_MS > fireDelayMs)
{
fireDelayMs = DASLib.Service.OutputSquibChannel.DEFAULT_MIN_FIRE_DELAY_MS;
}
SquibFireDelayMS = fireDelayMs;
break;
case AllSensorDataFields.SquibBypassVoltageFilter:
break;
case AllSensorDataFields.SquibBypassCurrentFilter:
break;
case AllSensorDataFields.SquibArticleId:
if (Bridge == SensorConstants.BridgeType.SQUIB) { EID = node.InnerText; }
break;
case AllSensorDataFields.UserTags:
if (Bridge == SensorConstants.BridgeType.DigitalInput && string.IsNullOrEmpty(node.InnerText))
{
//When creating Digital Input sensors without a Tag, set to "Digital In" (FB 12941)
SetTags(new string[] { StringResources.Digital_In }, DbOperations.GetSQLCommand, DbOperations.TagsGet,
DbOperations.TagsGetId, DbOperations.TagsInsert);
}
else
{
SetTagsFromCommaSeparatedString(node.InnerText, DbOperations.GetSQLCommand, DbOperations.TagsGet,
DbOperations.TagsGetId, DbOperations.TagsInsert);
}
break;
case AllSensorDataFields.DigitalInputScaleMultiplier:
ScaleMultiplier.FromDbSerializeString(node.InnerText);
break;
case AllSensorDataFields.DigitalInputUnits:
DIUnits = node.InnerText;
break;
case AllSensorDataFields.DigitalInputSettingMode:
{
if (Enum.TryParse(node.InnerText, out DigitalInputModes iMode))
{
InputMode = iMode;
}
}
break;
case AllSensorDataFields.DigitalInputSettingName:
//SerialNumber;
break;
case AllSensorDataFields.DigitalOutputChannelDescription:
//SerialNumber
break;
case AllSensorDataFields.DigitalOutputDelayMS:
DigitalOutputDelayMS = Convert.ToDouble(node.InnerText);
break;
case AllSensorDataFields.DigitalOutputDurationMS:
DigitalOutputDurationMS = Convert.ToDouble(node.InnerText);
break;
case AllSensorDataFields.DigitalOutputLimitDuration:
DigitalOutputLimitDuration = Convert.ToBoolean(node.InnerText);
break;
case AllSensorDataFields.DigitalOutputOutputMode:
{
if (Enum.TryParse(node.InnerText, out DigitalOutputModes oMode))
{
DigitalOutputMode = oMode;
}
}
break;
case AllSensorDataFields.UartBaudRate:
UartBaudRate = Convert.ToUInt32(node.InnerText);
break;
case AllSensorDataFields.UartDataBits:
UartDataBits = Convert.ToUInt32(node.InnerText);
break;
case AllSensorDataFields.UartStopBits:
UartStopBits = (StopBits)Enum.Parse(typeof(StopBits), node.InnerText);
break;
case AllSensorDataFields.UartParity:
UartParity = (Parity)Enum.Parse(typeof(Parity), node.InnerText);
break;
case AllSensorDataFields.UartFlowControl:
//FB 30486 Hardcode FlowControl to NONE for UART sensor type
break;
case AllSensorDataFields.UartDataFormat:
UartDataFormat = (UartDataFormat)Enum.Parse(typeof(UartDataFormat), node.InnerText);
break;
case AllSensorDataFields.StreamInUDPAddress: StreamInUDPAddress = node.InnerText; break;
case AllSensorDataFields.StreamOutUDPAddress: StreamOutUDPAddress = node.InnerText; break;
case AllSensorDataFields.StreamOutUDPProfile: StreamOutUDPProfile = (UDPStreamProfile)Enum.Parse(typeof(UDPStreamProfile), node.InnerText); break;
case AllSensorDataFields.StreamOutUDPDataChannelId: StreamOutUDPDataChannelId = Convert.ToUInt16(node.InnerText); break;
case AllSensorDataFields.StreamOutUDPTimeChannelId: StreamOutUDPTimeChannelId = Convert.ToUInt16(node.InnerText); break;
case AllSensorDataFields.StreamOutUDPTmNSConfig: StreamOutUDPTmNSConfig = node.InnerText; break;
case AllSensorDataFields.StreamOutIRIGTimeDataPacketIntervalMs: StreamOutIRIGTimeDataPacketIntervalMs = Convert.ToUInt16(node.InnerText); break;
case AllSensorDataFields.StreamOutTMATSIntervalMs:
if (ushort.TryParse(node.InnerText, out ushort uTmp))
{
StreamOutTMATSIntervalMs = uTmp;
}
else { StreamOutTMATSIntervalMs = StreamOutputRecord.DEFAULT_TMATS_INTERVAL_MS; }
break;
case AllSensorDataFields.Broken: Broken = Convert.ToBoolean(node.InnerText); break;
case AllSensorDataFields.DoNotUse: DoNotUse = Convert.ToBoolean(node.InnerText); break;
case AllSensorDataFields.DatabaseId:
DatabaseId = Convert.ToInt32(node.InnerText, System.Globalization.CultureInfo.InvariantCulture);
break;
case AllSensorDataFields.FirstUseDate:
if (node.InnerText.Equals(INVALID_FIRSTUSEDATE))
{
FirstUseDate = null;
}
else
{
if (DateTime.TryParse(node.InnerText, System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None, out var dtTemp))
{
FirstUseDate = dtTemp;
}
else
{
APILogger.Log($"possible invalid first use date data: {node.InnerText}");
FirstUseDate = null;
}
}
break;
case AllSensorDataFields.LatestCalibrationId:
if (int.TryParse(node.InnerText, out int iTemp))
{
LatestCalibrationId = iTemp == INVALID_CALIBRATION_ID ? null : (int?)iTemp;
}
else
{
LatestCalibrationId = null;
APILogger.Log($"possible invalid latest calibration id: {node.InnerText}");
}
break;
case AllSensorDataFields.ACCouplingModeEnabled:
if (bool.TryParse(node.InnerText, out var b))
{
ACCouplingModeEnabled = b;
}
break;
case AllSensorDataFields.AssemblyName:
AssemblyName = node.InnerText; break;
case AllSensorDataFields.UsageCount:
if (int.TryParse(node.InnerText, out int iUsageCount))
{
if (iUsageCount == INVALID_USAGE_COUNT)
{
UsageCount = 0;
APILogger.Log($"Invalid usage count: {node.InnerText}");
}
else
{
UsageCount = iUsageCount;
}
}
else
{
UsageCount = 0;
APILogger.Log($"Possible invalid usage count: {node.InnerText}");
}
break;
case AllSensorDataFields.MaximumUsage:
if (int.TryParse(node.InnerText, out int iMaxUsage))
{
if (iMaxUsage == INVALID_MAXIMUM_USAGE)
{
MaximumUsage = 0;
APILogger.Log($"Invalid maximum usage: {node.InnerText}");
}
else
{
MaximumUsage = iMaxUsage;
}
}
else
{
MaximumUsage = 0;
APILogger.Log($"Possible invalid maximum usage: {node.InnerText}");
}
break;
//FB 43267
case AllSensorDataFields.SensitivityTolerancePercent:
if (double.TryParse(node.InnerText, NumberStyles.Any, CultureInfo.InvariantCulture, out double dSensitivityTolerancePercent))
{
if (dSensitivityTolerancePercent == INVALID_TOLERANCE_PERCENT)
{
SensitivityTolerancePercent = Constants.SENSITIVITY_CHANGE_TOLERANCE_PERCENT_DEFAULT;
APILogger.Log($"Invalid SensitivityTolerancePercent: {node.InnerText}");
}
else
{
SensitivityTolerancePercent = dSensitivityTolerancePercent;
}
}
else
{
SensitivityTolerancePercent = Constants.SENSITIVITY_CHANGE_TOLERANCE_PERCENT_DEFAULT;
APILogger.Log($"Possible invalid SensitivityTolerancePercent: {node.InnerText}");
}
break;
default: throw new NotSupportedException("SensorData::ProcessXMLElement unsupported field: " + field);
}
}
}
private enum AllSensorDataFields
{
SerialNumber = 1,
UserSerialNumber,
Model,
Manufacturer,
Status,
MeasurementUnit,
OffsetToleranceLow,
OffsetToleranceHigh,
Id,
Capacity,
Comment,
BridgeType,
BridgeLegMode,
Shunt,
Invert,
UserValue1,
UserValue2,
UserValue3,
FilterClass,
BridgeResistance,
IsoCode,
CheckOffset,
SupportedExcitation,
InitialEU,
CalInterval,
CalibrationSignal,
InternalShuntResistance,
ExternalShuntResistance,
UniPolar,
RangeLow,
RangeAve,
RangeHigh,
Created,
TimesUsed,
SensorCategory,
BypassFilter,
CouplingMode,
Version,
LastModified,
ModifiedBy,
LocalOnly,
AxisNumber,
NumberOfAxes,
//digitaloutputs
DigitalOutputChannelDescription,
DigitalOutputDelayMS,
DigitalOutputDurationMS,
DigitalOutputOutputMode,
DigitalOutputLimitDuration,
//squibs
SquibDescription,
SquibBypassCurrentFilter,
SquibBypassVoltageFilter,
SquibDelayMS,
SquibDurationMS,
SquibFireMode,
SquibISOCode,
SquibMeasurementType,
SquibSquibOutputCurrent,
SquibSquibToleranceLow,
SquibSquibToleranceHigh,
SquibLimitDuration,
SquibArticleId,
//digital inputs
DigitalInputSettingName,
DigitalInputSettingMode,
DigitalInputScaleMultiplier,
DigitalInputUnits,
//uarts
UartBaudRate,
UartDataBits,
UartStopBits,
UartParity,
UartFlowControl,
UartDataFormat,
//streamins
StreamInUDPAddress,
//streamouts
StreamOutUDPAddress,
StreamOutUDPProfile,
StreamOutUDPDataChannelId,
StreamOutUDPTimeChannelId,
StreamOutUDPTmNSConfig,
StreamOutIRIGTimeDataPacketIntervalMs,
//tags
UserTags,
Broken,
DoNotUse,
DiagnosticsMode,
IsoChannelName,
UserCode,
UserChannelName,
DatabaseId,
LatestCalibrationId,
FirstUseDate,
ACCouplingModeEnabled,
AssemblyName,
UsageCount,
MaximumUsage,
StreamOutTMATSIntervalMs,
SensitivityTolerancePercent
}
private const string INVALID_FIRSTUSEDATE = "---";
public void WriteXML(ref System.Xml.XmlWriter writer, bool exportFirstUseDate = true)
{
writer.WriteStartElement("SensorData");
var fields = Enum.GetValues(typeof(AllSensorDataFields)).Cast<AllSensorDataFields>().ToArray();
foreach (var f in fields)
{
if (!exportFirstUseDate && (f == AllSensorDataFields.LatestCalibrationId || f == AllSensorDataFields.FirstUseDate))
{
continue;//skip, don't export
}
writer.WriteStartElement(f.ToString());
switch (f)
{
case AllSensorDataFields.AxisNumber: writer.WriteString(AxisNumber.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.BridgeLegMode: writer.WriteString(BridgeLegMode.ToString()); break;
case AllSensorDataFields.BridgeResistance: writer.WriteString(BridgeResistance.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.BridgeType: writer.WriteString(Bridge.ToString()); break;
case AllSensorDataFields.BypassFilter: writer.WriteString(ByPassFilter.ToString()); break;
case AllSensorDataFields.InitialEU: break;
case AllSensorDataFields.CalibrationSignal: writer.WriteString(CheckCalibrationSignal.ToString()); break;
case AllSensorDataFields.CalInterval: writer.WriteString(CalInterval.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.Capacity: writer.WriteString(Capacity.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.CheckOffset: writer.WriteString(CheckOffset.ToString()); break;
case AllSensorDataFields.Comment: writer.WriteString(Comment); break;
case AllSensorDataFields.CouplingMode: writer.WriteString(CouplingMode.ToString()); break;
case AllSensorDataFields.Created: writer.WriteString(Created.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.ExternalShuntResistance: writer.WriteString(ExternalShuntResistance.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.FilterClass: writer.WriteString(Filter.ToString()); break;
case AllSensorDataFields.Id: writer.WriteString(EID); break;
case AllSensorDataFields.InternalShuntResistance: writer.WriteString(InternalShuntResistance.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.Invert: writer.WriteString(Invert.ToString()); break;
case AllSensorDataFields.IsoCode: writer.WriteString(ISOCode); break;
case AllSensorDataFields.IsoChannelName: writer.WriteString(ISOChannelName); break;
case AllSensorDataFields.LastModified: writer.WriteString(LastModified.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.LocalOnly: writer.WriteString(LocalOnly.ToString()); break;
case AllSensorDataFields.Manufacturer: writer.WriteString(Manufacturer); break;
case AllSensorDataFields.MeasurementUnit: writer.WriteString(DisplayUnit); break;
case AllSensorDataFields.Model: writer.WriteString(Model); break;
case AllSensorDataFields.ModifiedBy: writer.WriteString(LastUpdatedBy); break;
case AllSensorDataFields.NumberOfAxes: writer.WriteString(NumberOfAxes.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.OffsetToleranceHigh: writer.WriteString(OffsetToleranceHigh.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.OffsetToleranceLow: writer.WriteString(OffsetToleranceLow.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.RangeAve: writer.WriteString(RangeMedium.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.RangeHigh: writer.WriteString(RangeHigh.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.RangeLow: writer.WriteString(RangeLow.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.SensorCategory: writer.WriteString(SensorCategory.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.SerialNumber: writer.WriteString(SerialNumber); break;
case AllSensorDataFields.Shunt: writer.WriteString(Shunt.ToString()); break;
case AllSensorDataFields.Status: writer.WriteString(Status.ToString()); break;
case AllSensorDataFields.SupportedExcitation: { writer.WriteString(string.Join(System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator, SupportedExcitation.Select(se => se.ToString()).ToArray())); } break;
case AllSensorDataFields.TimesUsed: writer.WriteString(TimesUsed.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.UniPolar: writer.WriteString(UniPolar.ToString()); break;
case AllSensorDataFields.UserCode: writer.WriteString(UserCode); break;
case AllSensorDataFields.UserChannelName: writer.WriteString(UserChannelName); break;
case AllSensorDataFields.UserSerialNumber: writer.WriteString(UserSerialNumber); break;
case AllSensorDataFields.DiagnosticsMode: writer.WriteString(DiagnosticsMode.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.UserValue1: writer.WriteString(UserValue1); break;
case AllSensorDataFields.UserValue2: writer.WriteString(UserValue2); break;
case AllSensorDataFields.UserValue3: writer.WriteString(UserValue3); break;
case AllSensorDataFields.Version: writer.WriteString(Version.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.SquibArticleId: writer.WriteString(EID); break;//shares Id property
case AllSensorDataFields.SquibBypassCurrentFilter: writer.WriteValue(BypassCurrentFilter); break;
case AllSensorDataFields.SquibBypassVoltageFilter: writer.WriteValue(BypassVoltageFilter); break;
case AllSensorDataFields.SquibDelayMS: writer.WriteString(SquibFireDelayMS.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.SquibDescription: writer.WriteString(SerialNumber); break;
case AllSensorDataFields.SquibDurationMS: writer.WriteString(SquibFireDurationMS.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.SquibFireMode: writer.WriteString(SquibFireMode.ToString()); break;
case AllSensorDataFields.SquibISOCode: writer.WriteString(ISOCode); break;
case AllSensorDataFields.SquibLimitDuration: writer.WriteValue(LimitDuration); break;
case AllSensorDataFields.SquibMeasurementType: writer.WriteString(SquibMeasurementType.ToString()); break;
case AllSensorDataFields.SquibSquibOutputCurrent: writer.WriteString(SquibOutputCurrent.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.SquibSquibToleranceHigh: writer.WriteString(SquibToleranceHigh.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.SquibSquibToleranceLow: writer.WriteString(SquibToleranceLow.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.DigitalInputScaleMultiplier: writer.WriteString(ScaleMultiplier.ToSerializeDbString()); break;
case AllSensorDataFields.UserTags: writer.WriteString(GetTagsAsCommaSeparatedString(DbOperations.TagsGet)); break;
case AllSensorDataFields.DigitalInputSettingMode: writer.WriteString(InputMode.ToString()); break;
case AllSensorDataFields.DigitalInputUnits: writer.WriteString(DIUnits.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.DigitalInputSettingName: writer.WriteString(SerialNumber); break;
case AllSensorDataFields.DigitalOutputChannelDescription: writer.WriteString(SerialNumber); break;
case AllSensorDataFields.DigitalOutputDelayMS: writer.WriteString(DigitalOutputDelayMS.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.DigitalOutputDurationMS: writer.WriteString(DigitalOutputDurationMS.ToString(System.Globalization.CultureInfo.InvariantCulture)); break;
case AllSensorDataFields.DigitalOutputLimitDuration: writer.WriteValue(DigitalOutputLimitDuration); break;
case AllSensorDataFields.DigitalOutputOutputMode: writer.WriteString(DigitalOutputMode.ToString()); break;
case AllSensorDataFields.UartBaudRate: writer.WriteString(UartBaudRate.ToString()); break;
case AllSensorDataFields.UartDataBits: writer.WriteString(UartDataBits.ToString()); break;
case AllSensorDataFields.UartStopBits: writer.WriteString(UartStopBits.ToString()); break;
case AllSensorDataFields.UartParity: writer.WriteString(UartParity.ToString()); break;
case AllSensorDataFields.UartFlowControl: writer.WriteString(UartFlowControl.ToString()); break;
case AllSensorDataFields.UartDataFormat: writer.WriteString(UartDataFormat.ToString()); break;
case AllSensorDataFields.StreamInUDPAddress: writer.WriteString(StreamInUDPAddress); break;
case AllSensorDataFields.StreamOutUDPAddress: writer.WriteString(StreamOutUDPAddress); break;
case AllSensorDataFields.StreamOutUDPProfile: writer.WriteString(StreamOutUDPProfile.ToString()); break;
case AllSensorDataFields.StreamOutUDPDataChannelId: writer.WriteString(StreamOutUDPDataChannelId.ToString()); break;
case AllSensorDataFields.StreamOutUDPTimeChannelId: writer.WriteString(StreamOutUDPTimeChannelId.ToString()); break;
case AllSensorDataFields.StreamOutTMATSIntervalMs: writer.WriteString(StreamOutTMATSIntervalMs.ToString()); break;
case AllSensorDataFields.StreamOutUDPTmNSConfig: writer.WriteString(StreamOutUDPTmNSConfig); break;
case AllSensorDataFields.StreamOutIRIGTimeDataPacketIntervalMs: writer.WriteString(StreamOutIRIGTimeDataPacketIntervalMs.ToString()); break;
case AllSensorDataFields.Broken: writer.WriteString(Broken.ToString()); break;
case AllSensorDataFields.DoNotUse: writer.WriteString(DoNotUse.ToString()); break;
case AllSensorDataFields.DatabaseId:
writer.WriteString(DatabaseId.ToString(System.Globalization.CultureInfo.InvariantCulture));
break;
case AllSensorDataFields.LatestCalibrationId:
if (null == LatestCalibrationId)
{
writer.WriteString(
INVALID_CALIBRATION_ID.ToString(System.Globalization.CultureInfo.InvariantCulture));
}
else
{
writer.WriteString(
((int)LatestCalibrationId).ToString(System.Globalization.CultureInfo
.InvariantCulture));
}
break;
case AllSensorDataFields.FirstUseDate:
if (null == FirstUseDate)
{
writer.WriteString(INVALID_FIRSTUSEDATE);
}
else
{
writer.WriteString(((DateTime)FirstUseDate).ToString("d",
System.Globalization.CultureInfo.InvariantCulture));
}
break;
case AllSensorDataFields.ACCouplingModeEnabled:
writer.WriteString(ACCouplingModeEnabled.ToString(System.Globalization.CultureInfo.InvariantCulture));
break;
case AllSensorDataFields.AssemblyName:
writer.WriteString(AssemblyName); break;
case AllSensorDataFields.UsageCount:
writer.WriteString(UsageCount.ToString(System.Globalization.CultureInfo
.InvariantCulture));
break;
case AllSensorDataFields.MaximumUsage:
writer.WriteString(MaximumUsage.ToString(System.Globalization.CultureInfo
.InvariantCulture));
break;
//FB 43267
case AllSensorDataFields.SensitivityTolerancePercent:
writer.WriteString(SensitivityTolerancePercent.ToString(System.Globalization.CultureInfo
.InvariantCulture));
break;
default: throw new NotSupportedException("SensorData::WriteXML unsupported field: " + f);
}
writer.WriteEndElement();
}
writer.WriteEndElement();
}
private const int INVALID_CALIBRATION_ID = -1;
private const int INVALID_USAGE_COUNT = -1;
private const int INVALID_MAXIMUM_USAGE = -1;
private const double INVALID_TOLERANCE_PERCENT = -1;
public enum ExchangeFields
{
SerialNumber = 1,
UserSerialNumber,
Model,
Manufacturer,
Status,
MeasurementUnit,
Id,
Capacity,
Comment,
IsProportional,
BridgeType,
Shunt,
Invert,
RemoveOffset,
UserValue1,
UserValue2,
UserValue3,
FilterClass,
BridgeResistance,
IsoCode,
IsoLongName,
CheckOffset,
ExcitationVoltage,
InitialEU,
CalibrationDate,
CalibrationDueDate,
Sensitivity,
CalUser,
CalZMO,
OffsetToleranceLow,
OffsetToleranceHigh,
OffsetMethod,
FiringDelay,
FiringDuration,
FireMode,
CurrentLimit,
InputMode,
SWOffsetCalculationStartSec,
SWOffsetCalculationEndSec,
SWOffsetCompensationType
}
private string _UUID = "";
public string UUID
{
get => _UUID;
set => _UUID = value;
}
public string GetSerialNumberWithAxis(string format)
{
if (SensorConstants.IsTestSpecificSquib(SerialNumber))
{
return StringResources.Value_NA;
}
if (SensorConstants.IsTestSpecificDigitalOut(SerialNumber))
{
return StringResources.Value_NA;
}
if (SensorConstants.IsTestSpecificEmbedded(SerialNumber)
||SensorConstants.IsTestSpecificThermoCouple(SerialNumber)
||SensorConstants.IsTestSpecificCAN(SerialNumber))
{
return StringResources.Value_NA;
}
if (1 == NumberOfAxes) { return SerialNumber; }
var serial = SerialNumber;
var axis = AxisNumber;
if (0 == axis) { }
else
{
var key = $"_axis_{axis}";
serial = serial.Replace(key, "");
}
return string.Format(format, serial, 1 + axis);
}
private string _diUnits = "V"; //Initialize to "V" because that's what data exports of DI channels have defaulted to in the past
public string DIUnits
{
get => _diUnits;
set
{
if (value == null)
{
value = "";
}
SetProperty(ref _diUnits, value, "DIUnits");
}
}
public string EID
{
get => EId;
set
{
if (value == null)
{
value = "";
}
EId = value;
OnPropertyChanged("EID");
}
}
private const double INVALID_SHUNT = 0D;
public bool PerformShuntEmulation
{
get
{
if (Shunt == ShuntMode.Emulation)
{
if (BridgeResistance == INVALID_SHUNT) { return false; }
switch (Bridge)
{
case SensorConstants.BridgeType.FullBridge:
case SensorConstants.BridgeType.HalfBridge:
case SensorConstants.BridgeType.QuarterBridge:
return true;
case SensorConstants.BridgeType.HalfBridge_SigPlus:
default:
return false;
}
}
return false;
}
}
public bool CalSignal
{
get => base.CalibrationSignal;
set
{
base.CalibrationSignal = value;
OnPropertyChanged("CalSignal");
}
}
public string GetSerializedSupportedExcitation()
{
return string.Join(System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator, SupportedExcitation.Select(sp => sp.ToString()).ToArray());
}
public bool ByPassFilter
{
get => BypassFilter;
set
{
BypassFilter = value;
OnPropertyChanged("ByPassFilter");
}
}
public bool CheckCalibrationSignal
{
get => base.CalibrationSignal;
set
{
base.CalibrationSignal = value;
OnPropertyChanged("CheckCalibrationSignal");
}
}
public string TestObject
{
get => new IsoCode(ISOCode).TestObject;
set
{
var ic = new IsoCode(ISOCode) { TestObject = value };
ISOCode = ic.StringRepresentation;
OnPropertyChanged("TestObject");
}
}
public string OriginalPosition { get; set; }
public string Position
{
get
{
var ic = new IsoCode(ISOCode);
return ic.Position;
}
set
{
var ic = new IsoCode(ISOCode);
ic.Position = value;
ISOCode = ic.StringRepresentation;
OnPropertyChanged("Position");
}
}
public string MainLocation
{
get
{
var ic = new IsoCode(ISOCode);
return ic.MainLocation;
}
set
{
var ic = new IsoCode(ISOCode);
ic.MainLocation = value;
ISOCode = ic.StringRepresentation;
OnPropertyChanged("MainLocation");
}
}
public string FineLocation1
{
get
{
var ic = new IsoCode(ISOCode);
return ic.FineLocation1;
}
set
{
var ic = new IsoCode(ISOCode);
ic.FineLocation1 = value;
ISOCode = ic.StringRepresentation;
OnPropertyChanged("FineLocation1");
}
}
public string FineLocation2
{
get
{
var ic = new IsoCode(ISOCode);
return ic.FineLocation2;
}
set
{
var ic = new IsoCode(ISOCode);
ic.FineLocation2 = value;
ISOCode = ic.StringRepresentation;
OnPropertyChanged("FineLocation2");
}
}
public string FineLocation3
{
get
{
var ic = new IsoCode(ISOCode);
return ic.FineLocation3;
}
set
{
var ic = new IsoCode(ISOCode);
ic.FineLocation3 = value;
ISOCode = ic.StringRepresentation;
OnPropertyChanged("FineLocation3");
}
}
public SensorData()
{
//13034 Partial list of available ISO codes with Default Filter when adding new sensors
//ISOCode = BuildIsoCodeFromFilter(null, Filter.FClass);
}
public int CompareTo(SensorData other)
{
return string.Compare(SerialNumber, other.SerialNumber, StringComparison.Ordinal);
}
public static bool IsValid(XElement elem)
{
try
{
var dummy = new SensorData(elem);
return true;
}
catch (Exception ex)
{
APILogger.Log(ex);
return false;
}
}
internal const string TOP_LEVEL_TAG = "SensorData";
internal const string SENSOR_TAG = "Sensor";
public enum SensorXMLFields
{
Version,
SerialNumber,
UserSerialNumber,
Model,
Status,
MeasurementUnit,
Sensitivity,
ID,
Capacity,
Comment,
IsPropotional,
Bridge,
CalSignal,
Shunt,
InternalShuntResistance,
ExternalShuntResistance,
BridgeResistance,
BridgeLegMode,
OffsetTolerance,
Invert,
RemoveOffset,
UserValue1,
UserValue2,
UserValue3,
Range,
Excitation,
Filter,
Zero,
InitialEU,
Created,
TimesUsed,
Zmo,
ISOCode,
ISOChannelName,
UserCode,
UserChannelName,
CheckOffset,
SIFFile,
IRTraccExponent,
SensorCategory,
FilterOption,
OriginalShuntMode,
OriginalZeroMethod,
Manufacturer,
CouplingMode,
IgnoreRange,
UniPolar,
NonLinear,
PolyStyle,
Dimension,
IRTraccFormat
};
public const string DATA_TABLE_FILENAME = "Data.SensorDB.xml";
private string _tableName;
internal void Init(XElement elem)
{
Calibration = new SensorCalibration();
_tableName = DATA_TABLE_FILENAME;
var ver = 0;
try
{
ver = (int)elem.Element(SensorXMLFields.Version.ToString());
}
catch (ArgumentNullException)
{
throw new Exception("SensorData: Can't find version tag in DB file");
}
Version = 1;
SensorDBBase.GetValue(elem, SensorXMLFields.SerialNumber.ToString(), out _serialNumber, null, _tableName);
SensorDBBase.GetValueSafe(elem, SensorXMLFields.UserSerialNumber.ToString(), out _userSerialNumber, SerialNumber, _tableName);
SensorDBBase.GetValueSafe(elem, SensorXMLFields.Model.ToString(), out _model, SerialNumber, _tableName);
SensorDBBase.GetValue(elem, SensorXMLFields.Status.ToString(), out _status, SerialNumber, _tableName);
SensorDBBase.GetValueSafe(elem, SensorXMLFields.MeasurementUnit.ToString(), out _displayUnit, SerialNumber, _tableName);
// This call insures that the display unit will be added to the list.
MeasurementUnitList.GetMeasurementUnit(_displayUnit);
// FB16398: set units on all records, not just first
Array.ForEach(Calibration.Records.Records, record => record.EngineeringUnits = _displayUnit); // FB6247 Sensor table not displaying Units correctly.
SensorDBBase.GetValueSafe(elem, SensorXMLFields.ID.ToString(), out var s, SerialNumber, _tableName);
//http://manuscript.dts.local/f/cases/31832/SLICEWare-to-DataPRO-Sensor-Database-EIDs-not-imported
EID = s;
SensorDBBase.GetValue(elem, SensorXMLFields.Capacity.ToString(), out _capacity, SerialNumber, _tableName);
SensorDBBase.GetValueSafe(elem, SensorXMLFields.Comment.ToString(), out string comment, SerialNumber, _tableName);
Comment = comment;
SensorDBBase.GetValue(elem, SensorXMLFields.IsPropotional.ToString(), out bool isProportional, SerialNumber, _tableName);
Calibration.IsProportional = isProportional;
SensorDBBase.GetValue(elem, SensorXMLFields.Bridge.ToString(), out _bridge, SerialNumber, _tableName);
SensorDBBase.GetValue(elem, SensorXMLFields.Shunt.ToString(), out ShuntMode shunt, SerialNumber, _tableName);
Shunt = shunt;
try
{
var newEl = SensorDBBase.GetTagValueSafe(elem, SensorXMLFields.CalSignal.ToString(), SerialNumber, _tableName);
if (null != newEl)
{
CalSignal = (bool)newEl;
}
else { CalSignal = false; }
}
catch (Exception ex)
{
APILogger.Log("Could not get ", SensorXMLFields.CalSignal.ToString(), " for ", SerialNumber, ex);
CalSignal = false;
}
SensorDBBase.GetValue(elem, SensorXMLFields.InternalShuntResistance.ToString(), out _internalShuntResistance, SerialNumber, _tableName);
SensorDBBase.GetValue(elem, SensorXMLFields.ExternalShuntResistance.ToString(), out _externalShuntResistance, SerialNumber, _tableName);
SensorDBBase.GetValue(elem, SensorXMLFields.BridgeResistance.ToString(), out _bridgeResistance, SerialNumber, _tableName);
if (double.IsNaN(BridgeResistance)) { BridgeResistance = 0D; }
BridgeLeg leg;
SensorDBBase.GetValue(elem, SensorXMLFields.BridgeLegMode.ToString(), out leg, SerialNumber, _tableName);
BridgeLegMode = leg;
var lowHi = new LowHigh(elem, SensorXMLFields.OffsetTolerance.ToString(), DATA_TABLE_FILENAME, SerialNumber);
_offsetToleranceLow = lowHi.Low;
_offsetToleranceHigh = lowHi.High;
var range = new SensorRange(elem, SensorXMLFields.Range.ToString(), DATA_TABLE_FILENAME, SerialNumber);
RangeMedium = range.Medium;
RangeHigh = range.High;
RangeLow = range.Low;
Filter = new FilterClass(elem, SensorXMLFields.Filter.ToString(), DATA_TABLE_FILENAME, SerialNumber);
Calibration.ZeroMethods = new ZeroMethods(new ZeroMethod(elem, SensorXMLFields.Zero.ToString(), DATA_TABLE_FILENAME, SerialNumber));
SensorDBBase.GetValue(elem, SensorXMLFields.Invert.ToString(), out string temp, SerialNumber, _tableName);
Invert = Convert.ToBoolean(temp);
SensorDBBase.GetValue(elem, SensorXMLFields.RemoveOffset.ToString(), out bool removeOffset, SerialNumber, _tableName);
Calibration.RemoveOffset = removeOffset;
SensorDBBase.GetValue(elem, SensorXMLFields.UserValue1.ToString(), out _userValue1, SerialNumber, _tableName);
SensorDBBase.GetValue(elem, SensorXMLFields.UserValue2.ToString(), out _userValue2, SerialNumber, _tableName);
SensorDBBase.GetValue(elem, SensorXMLFields.UserValue3.ToString(), out _userValue3, SerialNumber, _tableName);
SensorDBBase.GetValue(elem, SensorXMLFields.Excitation.ToString(), out ExcitationVoltageOptions.ExcitationVoltageOption option, SerialNumber, _tableName);
if (0 == option) { option = ExcitationVoltageOptions.ExcitationVoltageOption.Volt5; }
SupportedExcitation = new[] { option };
Calibration.Records.Records[0].Excitation = option;
SensorDBBase.GetValue(elem, SensorXMLFields.InitialEU.ToString(), out double initialeu, SerialNumber, _tableName);
Calibration.InitialOffsets.Offsets[0].Form = InitialOffsetTypes.EU;
Calibration.InitialOffsets.Offsets[0].EU = initialeu;
var bNonLinear = false;
//FB 6343 Old SLICEWare XML will not import.
try
{
var newEl = SensorDBBase.GetTagValueSafe(elem, SensorXMLFields.NonLinear.ToString(), SerialNumber,
_tableName);
if (null != newEl)
{
bNonLinear = (bool)newEl;
}
else
{
bNonLinear = false;
}
}
catch (Exception ex)
{
bNonLinear = false;
APILogger.Log(ex);
}
Calibration.NonLinear = bNonLinear;
SensorDBBase.GetValue(elem, SensorXMLFields.Created.ToString(), out _created, SerialNumber, _tableName);
SensorDBBase.GetValue(elem, SensorXMLFields.TimesUsed.ToString(), out int iTemp, SerialNumber, _tableName);
_timesUsed = iTemp;
//GetValue(elem, SensorXMLFields.Zmo.ToString(), out _Zmo, SerialNumber);
SensorDBBase.GetValue(elem, SensorXMLFields.ISOCode.ToString(), out temp, SerialNumber, _tableName);
ISOCode = temp;
SensorDBBase.GetValueSafe(elem, SensorXMLFields.ISOChannelName.ToString(), out temp, SerialNumber, _tableName);
ISOChannelName = temp ?? string.Empty;
SensorDBBase.GetValueSafe(elem, SensorXMLFields.UserCode.ToString(), out temp, SerialNumber, _tableName);
UserCode = temp ?? string.Empty;
SensorDBBase.GetValueSafe(elem, SensorXMLFields.UserChannelName.ToString(), out temp, SerialNumber, _tableName);
UserChannelName = temp ?? string.Empty;
SensorDBBase.GetValue(elem, SensorXMLFields.CheckOffset.ToString(), out temp, SerialNumber, _tableName);
CheckOffset = Convert.ToBoolean(temp);
try
{
var newEl = SensorDBBase.GetTagValueSafe(elem, SensorXMLFields.SensorCategory.ToString(), SerialNumber, _tableName);
if (null != newEl)
{
_sensorCategory = (int)newEl;
}
else { _sensorCategory = 0; }
}
catch (Exception) { _sensorCategory = 0; }
try
{
var newEl = SensorDBBase.GetTagValueSafe(elem, SensorXMLFields.FilterOption.ToString(), SerialNumber, _tableName);
if (null != newEl)
{
_bypassFilter = (bool)newEl;
}
else { _bypassFilter = false; }
}
catch (Exception) { _bypassFilter = false; }
try
{
var newEl = SensorDBBase.GetTagValueSafe(elem, SensorXMLFields.CouplingMode.ToString(), SerialNumber, _tableName);
if (null != newEl)
{
_couplingMode = (SensorConstants.CouplingModes)Enum.Parse(typeof(SensorConstants.CouplingModes), (string)newEl);
}
else { _couplingMode = SensorConstants.CouplingModes.DC; }
}
catch (Exception ex)
{
APILogger.Log("Could not get ", SensorXMLFields.CouplingMode.ToString(), " for ", SerialNumber, ex);
_couplingMode = SensorConstants.CouplingModes.DC;
}
try
{
var newEl = SensorDBBase.GetTagValueSafe(elem, SensorXMLFields.Manufacturer.ToString(), SerialNumber, _tableName);
if (null != newEl)
{
_manufacturer = (string)newEl;
}
}
catch (Exception) { _manufacturer = "unknown"; }
try
{
XElement tmp = null;
try { tmp = elem.Element(SensorXMLFields.IgnoreRange.ToString()); }
catch (Exception ex) { APILogger.Log(ex); }
if (null != tmp) { _IgnoreRange = (bool)tmp; }
}
catch (Exception ex) { APILogger.Log(ex); }
try
{
var tmp = elem.Element(SensorXMLFields.UniPolar.ToString());
if (null != tmp) { _uniPolar = (bool)tmp; }
}
catch (Exception ex) { APILogger.Log(ex); }
try
{
var tmp = elem.Element(SensorXMLFields.IRTraccFormat.ToString());
if (null == tmp) return;
if (Enum.TryParse((string)tmp, out NonLinearStyles style))
{
Calibration.Records.Records[0].Poly.NonLinearStyle = style;
}
}
catch (Exception ex) { APILogger.Log(ex); }
}
public SensorData(XElement elem)
{
Init(elem);
}
public bool SimpleEquals(SensorData rhs)
{
if (null == rhs) { return false; }
var fields = Enum.GetValues(typeof(AllSensorDataFields)).Cast<AllSensorDataFields>().ToArray();
if (Bridge == rhs.Bridge)
{
switch (Bridge)
{
case SensorConstants.BridgeType.DigitalInput:
return SerialNumber == rhs.SerialNumber
&& InputMode == rhs.InputMode
&& EID == rhs.EID
&& _digitalInputScaleMultiplier.Equals(rhs._digitalInputScaleMultiplier);
case SensorConstants.BridgeType.SQUIB:
return SerialNumber == rhs.SerialNumber
&& LimitSquibFireDuration == rhs.LimitSquibFireDuration
&& SquibFireDelayMS == rhs.SquibFireDelayMS
&& SquibFireMode == rhs.SquibFireMode
&& EID == rhs.EID
&& SquibMeasurementType == rhs.SquibMeasurementType
&& SquibOutputCurrent == rhs.SquibOutputCurrent
&& SquibToleranceHigh == rhs.SquibToleranceHigh
&& SquibToleranceLow == rhs.SquibToleranceLow;
case SensorConstants.BridgeType.TOMDigital:
return SerialNumber == rhs.SerialNumber
&& DigitalOutputDelayMS == rhs.DigitalOutputDelayMS
&& DigitalOutputDurationMS == rhs.DigitalOutputDurationMS
&& DigitalOutputLimitDuration == rhs.DigitalOutputLimitDuration
&& DigitalOutputMode == rhs.DigitalOutputMode;
case SensorConstants.BridgeType.FullBridge:
case SensorConstants.BridgeType.HalfBridge:
case SensorConstants.BridgeType.HalfBridge_SigPlus:
case SensorConstants.BridgeType.QuarterBridge:
case SensorConstants.BridgeType.IEPE:
default:
foreach (var field in fields)
{
switch (field)
{
case AllSensorDataFields.AxisNumber: if (AxisNumber != rhs.AxisNumber) { return false; } break;
case AllSensorDataFields.BridgeResistance: if (BridgeResistance != rhs.BridgeResistance) { return false; } break;
case AllSensorDataFields.CalInterval: if (CalInterval != rhs.CalInterval) { return false; } break;
case AllSensorDataFields.Capacity: if (Capacity != rhs.Capacity) { return false; } break;
case AllSensorDataFields.CheckOffset: if (CheckOffset != rhs.CheckOffset) { return false; } break;
case AllSensorDataFields.Comment: if (Comment != rhs.Comment) { return false; } break;
case AllSensorDataFields.MeasurementUnit: if (DisplayUnit != rhs.DisplayUnit) { return false; } break;
case AllSensorDataFields.Id: if (EID != rhs.EID) { return false; } break;
case AllSensorDataFields.Invert: if (Invert != rhs.Invert) { return false; } break;
case AllSensorDataFields.IsoCode: if (ISOCode != rhs.ISOCode) { return false; } break;
case AllSensorDataFields.NumberOfAxes: if (NumberOfAxes != rhs.NumberOfAxes) { return false; } break;
case AllSensorDataFields.SerialNumber: if (SerialNumber != rhs.SerialNumber) { return false; } break;
case AllSensorDataFields.Shunt: if (Shunt != rhs.Shunt) { return false; } break;
case AllSensorDataFields.Status: if (Status != rhs.Status) { return false; } break;
case AllSensorDataFields.OffsetToleranceHigh: if (OffsetToleranceHigh != rhs.OffsetToleranceHigh) { return false; } break;
case AllSensorDataFields.OffsetToleranceLow: if (OffsetToleranceLow != rhs.OffsetToleranceLow) { return false; } break;
case AllSensorDataFields.SupportedExcitation:
if (SupportedExcitation.Length == rhs.SupportedExcitation.Length)
{
foreach (var se in SupportedExcitation)
{
if (!rhs.SupportedExcitation.Contains(se)) { return false; }
}
}
else { return false; }
break;
}
}
return true;
}
}
return false;
}
public bool IncompatibleSensorAssignment(string sensorDimension, string channelDimension)
{
return sensorDimension != channelDimension &&
sensorDimension != "00" &&
sensorDimension != "SE" &&
!sensorDimension.Contains("?") &&
channelDimension != "00" &&
channelDimension != "SE" &&
!channelDimension.Contains("?");
}
public double InputActiveValue
{
get => ScaleMultiplier.ActiveValue;
set => ScaleMultiplier.ActiveValue = value;
}
public double InputDefaultValue
{
get => ScaleMultiplier.DefaultValue;
set => ScaleMultiplier.DefaultValue = value;
}
}
}