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,731 @@
using DTS.Common.Enums;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.Sensors;
using DTS.Common.Interface.Sensors.SoftwareFilters;
using DTS.Common.Interface.Tags;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.SqlTypes;
namespace DTS.Common.Classes.Sensors
{
/// <summary>
/// represents a record of an analog sensor in the db
/// <inheritdoc cref="IAnalogDbRecord"/>
/// </summary>
public class AnalogDbRecord : TagAwareBase, IAnalogDbRecord
{
public override TagTypes TagType => TagTypes.SensorModels;
protected int _id = -1;
/// <summary>
/// the database id of the sensor
/// </summary>
[Key]
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
protected string _serialNumber = "";
/// <summary>
/// Serial number of sensor
/// [required to be unique]
/// </summary>
[Required]
[StringLength(50)]
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
protected short _axisNumber = 0;
/// <summary>
/// deprecated
/// which axis the record is for when the sensor is multi-axis
/// </summary>
public short AxisNumber
{
get => _axisNumber;
set => SetProperty(ref _axisNumber, value, "AxisNumber");
}
protected short _bridgeLegMode;
/// <summary>
/// deprecated
/// </summary>
public short BridgeLegMode
{
get => _bridgeLegMode;
set => SetProperty(ref _bridgeLegMode, value, "BridgeLegMode");
}
protected double _bridgeResistance = 350D;
/// <summary>
/// the expected resistance in Ohms if applicable for the sensor
/// </summary>
public double BridgeResistance
{
get => _bridgeResistance;
set => SetProperty(ref _bridgeResistance, value, "BridgeResistance");
}
protected SensorConstants.BridgeType _bridge = SensorConstants.BridgeType.FullBridge;
/// <summary>
/// the type of bridge or sensor
/// [DO NOT USE BITMASKED VALUE WHEN READING/WRITING TO DB]
/// </summary>
public SensorConstants.BridgeType Bridge
{
get => _bridge;
set => SetProperty(ref _bridge, value, "Bridge");
}
protected void SetBridge(SensorConstants.BridgeType bridge)
{
_bridge = bridge;
}
protected bool _broken = false;
/// <summary>
/// Whether the sensor has been marked as broken by a user
/// </summary>
public bool Broken
{
get => _broken;
set => SetProperty(ref _broken, value, "Broken");
}
protected bool _bypassFilter = false;
/// <summary>
/// whether the sensor has it's own filtering or should otherwise bypass
/// hardware filters when collecting data
/// (not supported on all hardware)
/// </summary>
public bool BypassFilter
{
get => _bypassFilter;
set => SetProperty(ref _bypassFilter, value, "BypassFilter");
}
protected bool _calibrationSignal;
/// <summary>
/// deprecated?
/// </summary>
public bool CalibrationSignal
{
get => _calibrationSignal;
set => SetProperty(ref _calibrationSignal, value, "CalibrationSignal");
}
protected int _calInterval = 365;
/// <summary>
/// calibration interval in days, used in determining when sensor is out of cal
/// </summary>
public int CalInterval
{
get => _calInterval;
set => SetProperty(ref _calInterval, value, "CalInterval");
}
protected double _capacity = 2400D;
/// <summary>
/// capacity of the sensor in EU
/// </summary>
public double Capacity
{
get => _capacity;
set => SetProperty(ref _capacity, value, "Capacity");
}
protected bool _checkOffset = true;
/// <summary>
/// Whether to check the sensor output in mV against thresholds in diagnostics
/// </summary>
public bool CheckOffset
{
get => _checkOffset;
set => SetProperty(ref _checkOffset, value, "CheckOffset");
}
protected string _comment = "";
/// <summary>
/// user supplied descriptive comment on sensor
/// </summary>
[Required]
[StringLength(50)]
public string Comment
{
get => _comment;
set => SetProperty(ref _comment, value, "Comment");
}
protected SensorConstants.CouplingModes _couplingMode = SensorConstants.CouplingModes.AC;
/// <summary>
/// IEPE coupling mode to use for data collection if applicable
/// </summary>
public SensorConstants.CouplingModes CouplingMode
{
get => _couplingMode;
set => SetProperty(ref _couplingMode, value, "CouplingMode");
}
protected DateTime _created;
/// <summary>
/// date sensor record was created (if available)
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created
{
get => _created;
set => SetProperty(ref _created, value, "Created");
}
protected bool _diagnosticsMode = false;
/// <summary>
/// Whether this sensor should only record internal resistance and record no external signal
/// [generally only useful for testing purposes]
/// </summary>
public bool DiagnosticsMode
{
get => _diagnosticsMode;
set => SetProperty(ref _diagnosticsMode, value, "DiagnosticsMode");
}
protected string _displayUnit = "";
/// <summary>
/// engineering units collected data should be displayed in
/// note that calibration records are also tied against a specific engineering unit that should be used
/// the sensor db value is not used
/// </summary>
public string DisplayUnit
{
get => _displayUnit;
set => SetProperty(ref _displayUnit, value, "DisplayUnit");
}
protected bool _doNotUse = false;
/// <summary>
/// whether this sensor has been marked not to be used by user
/// </summary>
public bool DoNotUse
{
get => _doNotUse;
set => SetProperty(ref _doNotUse, value, "DoNotUse");
}
protected string _eId = "";
/// <summary>
/// Electronic Identification tag
/// [DALLAS or TEDS ID TAG]
/// if present required to be unique
/// </summary>
[Required]
[Column("eId")]
[StringLength(50)]
public string EId
{
get => _eId;
set => SetProperty(ref _eId, value, "EId");
}
protected double _externalShuntResistance;
/// <summary>
/// TDAS supports external resistance when measuring shunt resistance
/// this is the value of external resistance applied
/// </summary>
public double ExternalShuntResistance
{
get => _externalShuntResistance;
set => SetProperty(ref _externalShuntResistance, value, "ExternalShuntResistance");
}
private IFilterClass _filter= new FilterClass(FilterClassType.CFC1000);
/// <summary>
/// The default software filter class to apply to data channel when viewing
/// filtered EU data
/// </summary>
public IFilterClass Filter
{
get => _filter;
set => SetProperty(ref _filter, value, "Filter");
}
private double? _initialEU;
/// <summary>
/// Amount of EU to add in when EU is calculated
/// Used to offset EU readings by a specific amount
/// Note that analog sensor calibration records
/// can contain a more sophisticated EU offset
/// </summary>
[Column("InitialEU")]
[Required]
[StringLength(50)]
public double? InitialEu
{
get => _initialEU;
set => SetProperty(ref _initialEU, value, "InitialEu");
}
protected double _internalShuntResistance;
/// <summary>
/// TDAS supports performing external and internal resistance when measuring shunt resistance
/// This is the value to use when internal shunt resistance is used
/// </summary>
public double InternalShuntResistance
{
get => _internalShuntResistance;
set => SetProperty(ref _internalShuntResistance, value, "InternalShuntResistance");
}
protected bool _invert = false;
/// <summary>
/// whether output of the sensor in EU should be inverted or not
/// </summary>
public bool Invert
{
get => _invert;
set => SetProperty(ref _invert, value, "Invert");
}
private string _isoChannelName = string.Empty;
/// <summary>
/// ISO 13499 channel name to apply to a data channel when a data channel is
/// created using the sensor
/// </summary>
[Required]
[StringLength(255)]
public string ISOChannelName
{
get => _isoChannelName;
set => SetProperty(ref _isoChannelName, value, "ISOChannelName");
}
private string _isoCode = string.Empty;
/// <summary>
/// ISO 13499 code to apply to a data channel when a data channel is created
/// using the sensor
/// </summary>
[Required]
[StringLength(50)]
public string ISOCode
{
get => _isoCode;
set => SetProperty(ref _isoCode, value, "ISOCode");
}
private DateTime _lastModified = (DateTime)SqlDateTime.MinValue;
/// <summary>
/// when the sensor was last modified
/// </summary>
[Column(TypeName = "datetime")]
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
protected bool _localOnly = false;
/// <summary>
/// deprecated, used to determine which sensors should not propagate up to central database
/// </summary>
public bool LocalOnly
{
get => _localOnly;
set => SetProperty(ref _localOnly, value, "LocalOnly");
}
protected string _manufacturer = "";
/// <summary>
/// Maker of sensor
/// </summary>
[StringLength(50)]
public string Manufacturer
{
get => _manufacturer;
set => SetProperty(ref _manufacturer, value, "Manufacturer");
}
protected string _model = "";
/// <summary>
/// model of sensor
/// </summary>
[StringLength(50)]
public string Model
{
get => _model;
set => SetProperty(ref _model, value, "Model");
}
private string _modifiedBy = "";
/// <summary>
/// who last modified the sensor record
/// </summary>
[Required]
[StringLength(50)]
public string ModifiedBy
{
get => _modifiedBy;
set => SetProperty(ref _modifiedBy, value, "ModifiedBy");
}
private short _numberOfAxes = 1;
/// <summary>
/// deprecated/reserved
/// number of axes associated with this serial number
/// </summary>
public short NumberOfAxes
{
get => _numberOfAxes;
set => SetProperty(ref _numberOfAxes, value, "NumberOfAxes");
}
protected double _offsetToleranceHigh = SensorConstants.DefaultBridgeOffsetMVTolHigh;
/// <summary>
/// allowable tolerance in mV on the high side for an idle reading of sensor
/// used to determine if the sensor output is too high in diagnostics
/// </summary>
public double OffsetToleranceHigh
{
get => _offsetToleranceHigh;
set => SetProperty(ref _offsetToleranceHigh, value, "OffsetToleranceHigh");
}
protected double _offsetToleranceLow = SensorConstants.DefaultBridgeOffsetMVTolLow;
/// <summary>
/// allowable tolerance in mV on the low side for an idle reading of sensor
/// used to determine if the sensor output is too low in diagnostics
/// </summary>
public double OffsetToleranceLow
{
get => _offsetToleranceLow;
set => SetProperty(ref _offsetToleranceLow, value, "OffsetToleranceLow");
}
private double _rangeMedium;
/// <summary>
/// typical medium range for sensor in applications
/// </summary>
public double RangeMedium
{
get => 0 == _rangeMedium ? Capacity : _rangeMedium;
set => SetProperty(ref _rangeMedium, value, "RangeMedium");
}
private double _rangeHigh;
/// <summary>
/// typical high range for sensor in applications
/// </summary>
public double RangeHigh
{
get => 0 == _rangeHigh ? Capacity : _rangeHigh;
set => SetProperty(ref _rangeHigh, value, "RangeHigh");
}
private double _rangeLow;
/// <summary>
/// typical low range for sensor in applications
/// </summary>
public double RangeLow
{
get => 0 == _rangeLow ? Capacity : _rangeLow;
set => SetProperty(ref _rangeLow, value, "RangeLow");
}
protected int _sensorCategory;
/// <summary>
/// The type of sensor
/// Deprecated, remains for TDC purposes
/// Normal = 0,
/// POT = 1,
/// IRTracc = 2,
/// Polynomial = 3
/// </summary>
public int SensorCategory
{
get => _sensorCategory;
set => SetProperty(ref _sensorCategory, value, "SensorCategory");
}
private int _sensorModelId;
/// <summary>
/// the database id of the sensor model, if applicable
/// </summary>
public int SensorModelId
{
get => _sensorModelId;
set => SetProperty(ref _sensorModelId, value, "SensorModelId");
}
private const short SHUNT_MODE_EMULATION = 1;
protected short _shunt = SHUNT_MODE_EMULATION;
/// <summary>
/// The type of shunt used for measuring shunt results
/// note all SLICE hardware only supports emulation (or none)
/// None = 0,
/// Emulation = 1,
/// Internal = 2,
/// External = 3
/// </summary>
public short Shunt
{
get => _shunt;
set => SetProperty(ref _shunt, value, "Shunt");
}
protected SensorStatus _status = SensorStatus.Available;
[Required]
[StringLength(50)]
/// <summary>
/// reserved/not in use
/// </summary>
public SensorStatus Status
{
get => _status;
set => SetProperty(ref _status, value, "Status");
}
protected ExcitationVoltageOptions.ExcitationVoltageOption[] _supportedExcitation = new[] { ExcitationVoltageOptions.ExcitationVoltageOption.Volt5 };
/// <summary>
/// Excitation voltages supported by the sensor
/// used to prevent the sensor from being used in a situation that might damaged it
/// (say a 2V sensor being fed 10V excitation)
/// </summary>
[Required]
[StringLength(50)]
public ExcitationVoltageOptions.ExcitationVoltageOption[] SupportedExcitation
{
get => _supportedExcitation;
set => SetProperty(ref _supportedExcitation, value, "SupportedExcitation");
}
protected long _timesUsed;
/// <summary>
/// Reserved/Not used
/// </summary>
public long TimesUsed
{
get => _timesUsed;
set => SetProperty(ref _timesUsed, value, "TimesUsed");
}
protected bool _uniPolar = false;
/// <summary>
/// flag indicating that the sensor should be interpreted as 0-n rather than -x<0<x
/// </summary>
public bool UniPolar
{
get => _uniPolar;
set => SetProperty(ref _uniPolar, value, "UniPolar");
}
private string _userChannelName = string.Empty;
/// <summary>
/// User channel name to apply when sensor is applied to a blank channel
/// </summary>
[Required]
[StringLength(255)]
public string UserChannelName
{
get => _userChannelName;
set => SetProperty(ref _userChannelName, value, "UserChannelName");
}
private string _userCode = string.Empty;
/// <summary>
/// User channel code to apply when sensor is applied to a blank channel
/// </summary>
[Required]
[StringLength(50)]
public string UserCode
{
get => _userCode;
set => SetProperty(ref _userCode, value, "UserCode");
}
protected string _userSerialNumber = string.Empty;
[Required]
[StringLength(50)]
public string UserSerialNumber
{
get => _userSerialNumber;
set => SetProperty(ref _userSerialNumber, value, "UserSerialNumber");
}
protected string _userValue1 = string.Empty;
/// <summary>
/// user supplied string
/// travels with the sensor to data channels when
/// data is recorded with the sensor
/// </summary>
[StringLength(50)]
public string UserValue1
{
get => _userValue1;
set => SetProperty(ref _userValue1, value, "UserValue1");
}
protected string _userValue2 = string.Empty;
/// <summary>
/// user supplied string
/// travels with the sensor to data channels when
/// data is recorded with the sensor
/// </summary>
[StringLength(50)]
public string UserValue2
{
get => _userValue2;
set => SetProperty(ref _userValue2, value, "UserValue2");
}
protected string _userValue3 = string.Empty;
/// <summary>
/// user supplied string
/// travels with the sensor to data channels when
/// data is recorded with the sensor
/// </summary>
[StringLength(50)]
public string UserValue3
{
get => _userValue3;
set => SetProperty(ref _userValue3, value, "UserValue3");
}
private int _version = 1;
/// <summary>
/// deprecated
/// </summary>
public int Version
{
get => _version;
set => SetProperty(ref _version, value, "Version");
}
private DateTime? _firstUseDate;
[Column(TypeName = "datetime")]
/// <summary>
/// Date of first destructive use since sensor was calibrated,
/// only valid when using latest calibration
/// null indicates not set
/// </summary>
public DateTime? FirstUseDate
{
get => _firstUseDate;
set => SetProperty(ref _firstUseDate, value, "FirstUseDate");
}
private int? _latestCalibrationId;
/// <summary>
/// deprecated
/// Originally held the id of the latest calibration record
/// for sensor
/// </summary>
public int? LatestCalibrationId
{
get => _latestCalibrationId;
set => SetProperty(ref _latestCalibrationId, value, "LatestCalibrationId");
}
public AnalogDbRecord() { }
public AnalogDbRecord(IAnalogDbRecord copy)
{
AxisNumber = copy.AxisNumber;
Bridge = copy.Bridge;
BridgeLegMode = copy.BridgeLegMode;
BridgeResistance = copy.BridgeResistance;
BypassFilter = copy.BypassFilter;
CalibrationSignal = copy.CalibrationSignal;
CalInterval = copy.CalInterval;
Capacity = copy.Capacity;
CheckOffset = copy.CheckOffset;
Comment = copy.Comment;
CouplingMode = copy.CouplingMode;
Created = copy.Created;
ExternalShuntResistance = copy.ExternalShuntResistance;
Filter = new FilterClass(copy.Filter.FClass, copy.Filter.Frequency);
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;
ModifiedBy = copy.ModifiedBy;
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;
DiagnosticsMode = copy.DiagnosticsMode;
UserValue1 = copy.UserValue1;
UserValue2 = copy.UserValue2;
UserValue3 = copy.UserValue3;
Version = copy.Version;
SupportedExcitation = copy.SupportedExcitation;
TagsBlobBytes = copy.TagsBlobBytes;
DoNotUse = copy.DoNotUse;
Broken = copy.Broken;
Id = copy.Id;
FirstUseDate = copy.FirstUseDate;
LatestCalibrationId = copy.LatestCalibrationId;
ACCouplingModeEnabled = copy.ACCouplingModeEnabled;
}
public AnalogDbRecord(IDataReader reader)
{
AxisNumber = Utility.GetShort(reader, "AxisNumber", 0);
SetBridge(SensorConstants.ConvertIntToBridgeType(Utility.GetInt(reader, "BridgeType")));
BridgeLegMode = Utility.GetShort(reader, "BridgeLegMode", 0);
BridgeResistance = Utility.GetDouble(reader, "BridgeResistance");
BypassFilter = Utility.GetBool(reader, "BypassFilter");
CalibrationSignal = Utility.GetBool(reader, "CalibrationSignal");
CalInterval = Utility.GetInt(reader, "CalInterval");
Capacity = Utility.GetDouble(reader, "Capacity");
CheckOffset = Utility.GetBool(reader, "CheckOffset");
Comment = Utility.GetString(reader, "Comment");
CouplingMode = (SensorConstants.CouplingModes)Utility.GetInt(reader, "CouplingMode");
Created = Utility.GetDateTime(reader, "Created", DateTime.MinValue);
ExternalShuntResistance = Utility.GetDouble(reader, "ExternalShuntResistance");
Filter = new FilterClass(Utility.GetString(reader, "FilterClass"));
EId = Utility.GetString(reader, "eId");
InternalShuntResistance = Utility.GetDouble(reader, "InternalShuntResistance");
Invert = Utility.GetBool(reader, "Invert");
ISOCode = Utility.GetString(reader, "IsoCode");
ISOChannelName = Utility.GetString(reader, "IsoChannelName");
UserCode = Utility.GetString(reader, "UserCode");
UserChannelName = Utility.GetString(reader, "UserChannelName");
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LocalOnly = Utility.GetBool(reader, "LocalOnly", false);
Manufacturer = Utility.GetString(reader, "Manufacturer");
DisplayUnit = Utility.GetString(reader, "MeasurementUnit");
Model = Utility.GetString(reader, "Model");
ModifiedBy = Utility.GetString(reader, "ModifiedBy");
NumberOfAxes = Utility.GetShort(reader, "NumberOfAxes");
OffsetToleranceHigh = Utility.GetDouble(reader, "OffsetToleranceHigh");
OffsetToleranceLow = Utility.GetDouble(reader, "OffsetToleranceLow");
RangeMedium = Utility.GetDouble(reader, "RangeAve");
RangeHigh = Utility.GetDouble(reader, "RangeHigh");
RangeLow = Utility.GetDouble(reader, "RangeLow");
SensorCategory = Utility.GetInt(reader, "SensorCategory");
SerialNumber = Utility.GetString(reader, "SerialNumber");
Shunt = Utility.GetShort(reader, "Shunt");
var oStatus = reader["Status"];
if (oStatus is string s)
{
if (Enum.TryParse(s, out SensorStatus newStatus))
{
Status = newStatus;
}
}
else
{
Status = (SensorStatus)Convert.ToInt32(oStatus);
}
TimesUsed = Utility.GetInt(reader, "TimesUsed");
UniPolar = Utility.GetBool(reader, "UniPolar");
UserSerialNumber = Utility.GetString(reader, "UserSerialNumber");
DiagnosticsMode = Utility.GetBool(reader, "DiagnosticsMode");
UserValue1 = Utility.GetString(reader, "UserValue1");
UserValue2 = Utility.GetString(reader, "UserValue2");
UserValue3 = Utility.GetString(reader, "UserValue3");
Version = Utility.GetInt(reader, "Version");
SetSupportedExcitationFromString(Utility.GetString(reader, "SupportedExcitation"));
TagsBlobBytes = (byte[])reader["UserTags"];
DoNotUse = Utility.GetBool(reader, "DoNotUse");
Broken = Utility.GetBool(reader, "Broken");
Id = Utility.GetInt(reader, "Id", -1);
FirstUseDate = Utility.GetNullableDateTime(reader, "FirstUseDate");
LatestCalibrationId = Utility.GetNullableInt(reader, "LatestCalibrationId");
ACCouplingModeEnabled = Utility.GetBool(reader, "ACCouplingModeEnabled", false);
}
public void SetSupportedExcitationFromString(string s)
{
var excitations = new List<ExcitationVoltageOptions.ExcitationVoltageOption>();
var tokens = s.Split(new[] { System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator }, StringSplitOptions.None);
foreach (var token in tokens)
{
if (Enum.TryParse(token, out ExcitationVoltageOptions.ExcitationVoltageOption option)) { excitations.Add(option); }
}
SupportedExcitation = excitations.ToArray();
}
private bool _bACCouplingModeEnabled = false;
/// <summary>
/// whether to use AC Coupling when using a bridge mode (full/half/quarter/half+sig)
/// 18294 Implement Bridge AC/DC coupling(fw update dependent)
/// </summary>
public bool ACCouplingModeEnabled
{
get => _bACCouplingModeEnabled;
set => SetProperty(ref _bACCouplingModeEnabled, value, "ACCouplingModeEnabled");
}
}
}

View File

@@ -0,0 +1,148 @@
using DTS.Common.Enums.Sensors;
namespace DTS.Common.Interface.Hardware
{
public interface IDiagnosticResult
{
/// <summary>
/// Which DASChannel from which this diagnostics is returning.
/// </summary>
int DASChannelNumber { get; set; }
/// <summary>
/// The event number that this diagnostics is relevant for.
/// </summary>
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>
double ScalefactorMilliVoltsPerADC { get; set; }
/// <summary>
/// The factory excitation value (mandatory)
/// </summary>
double ExpectedExcitationMilliVolts { get; set; }
/// <summary>
/// gets what will probably be the datazerolevel adc for the channel
/// </summary>
/// <param name="zeroMethod"></param>
/// <returns></returns>
short GetExpectedDataZeroLevelADC(ZeroMethodType zeroMethod);
/// <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>
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>
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>
double? MeasuredOffsetMilliVolts{ get; set; }
double? MeasuredInternalOffsetMilliVolts{ 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>
double? AutoZeroPercentDeviation{ get; set; }
/// <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>
short? FinalOffsetADC { get; set; }
int? RemovedOffsetADC { get; set; }
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>
double? NoisePercentFullScale { get; set; }
bool ShuntDeflectionFailed { get; set; }
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>
double? MeasuredShuntDeflectionMv { get; set; }
double? MeasuredCalSignalMv { get; set; }
double? TargetCalSignalMv { get; set; }
double? MeasuredDurationMS { get; set; }
double? MeasuredDelayMS { get; set; }
bool? SquibFirePassed { get; set; }
bool? SquibDurationPassed { get; set; }
bool? SquibDelayPassed { get; set; }
double[] SquibFireCurrentData { get; set; }
double[] SquibFireVoltageData { get; set; }
double[] SquibFireTimeAxis { get; set; }
double SquibThreshold { get; set; }
double SquibVoltageScaler { get; set; }
double SquibCurrentScaler { get; set; }
double? TargetGain { get; set; }
double? MeasuredGain { get; set; }
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>
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>
double? BridgeResistance { get; set; }
short ZeroMVInADC { get; set; }
/// <summary>
/// WindowAverageADC is the average ADC over the averaging window specified for the channel
/// short.MinValue indicates an unitialized or invalid value
/// </summary>
short WindowAverageADC { get; set; }
bool DigitalInputActiveState { get; set; }
}
}

View File

@@ -0,0 +1,233 @@
using DTS.Common.Utilities.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace DTS.Common.Utils
{
//FB 18512 This calss contains utility methods, they are moved from Netwroking module
public static class NetworkUtils
{
/// <summary>
/// returns true if the network interface is up, false otherwise
/// stolen from FWTU
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
public static bool IsNetworkInterfaceUp(IPAddress ip)
{
foreach (var a in NetworkInterface.GetAllNetworkInterfaces())
{
try
{
var ipp = a.GetIPProperties();
if (ipp.MulticastAddresses.Count == 0)
continue; // most of VPN adapters will be skipped
if (!a.SupportsMulticast)
continue; // multicast is meaningless for this type of connection
if (OperationalStatus.Up != a.OperationalStatus)
continue; // this adapter is off or not connected
if (null == ipp.GetIPv4Properties())
continue; // IPv4 is not configured on this adapter
if (a.NetworkInterfaceType == NetworkInterfaceType.Loopback)
continue;
var addressBytes = ip.GetAddressBytes();
if (4 == addressBytes.Length && addressBytes[0] == 169 && addressBytes[1] == 254) { continue; }
if (a.GetIPProperties().UnicastAddresses.Any(i => i.Address.AddressFamily == AddressFamily.InterNetwork && IPAddress.Equals(i.Address, ip)))
{
return true;
}
}
catch (Exception)
{
continue;
}
}
return false;
}
/// <summary>
/// Indicates whether any network connection is available.
/// Filter connections below a specified speed, as well as virtual network cards.
/// </summary>
/// <param name="minimumSpeed">The minimum speed required. Passing 0 will not filter connection using speed.</param>
/// <returns>
/// <c>true</c> if a network connection is available; otherwise, <c>false</c>.
/// </returns>
private static List<NetworkInterface> GetAvailableNetworkInterfaces(long minimumSpeed = 10000000)
{
if (!NetworkInterface.GetIsNetworkAvailable())
return null;
var niList = new List<NetworkInterface>();
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
{
// discard because of standard reasons
if ((ni.NetworkInterfaceType == NetworkInterfaceType.Loopback)
|| (ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel))
continue;
// this allow to filter modems, serial, etc.
// use 10000000 as a minimum speed for most cases
if (ni.Speed < minimumSpeed)
continue;
// discard virtual cards (virtual box, virtual pc, etc.)
if (ni.Description.ToLower().Contains("virtual")
|| ni.Name.ToLower().Contains("virtual")
|| ni.Description.ToLower().Contains("bluethooth")
|| ni.Name.ToLower().Contains("bluethooth"))
continue;
// discard "Microsoft Loopback Adapter", it will not show as NetworkInterfaceType.Loopback but as Ethernet Card.
if (ni.Description.Equals("Microsoft Loopback Adapter", StringComparison.OrdinalIgnoreCase))
continue;
niList.Add(ni);
}
return niList;
}
private static string GetMACAddress(string id)
{
var macAddress = string.Empty;
var nics = GetAvailableNetworkInterfaces();
if (nics == null)
return macAddress;
foreach (var nic in nics)
{
if (nic.Id != id) continue;
var pa = BitConverter.ToString(nic.GetPhysicalAddress().GetAddressBytes());
pa = pa.Replace("-", ":");
if (string.IsNullOrEmpty(pa)) continue;
macAddress = pa;
break;
}
return macAddress;
}
private static bool InvalidNIC(NetworkInterface ni)
{
return OperationalStatus.Up != ni.OperationalStatus || !ni.SupportsMulticast;
}
public static List<HostInfo> GetAvailableHosts(bool supportMulticastOnly = false)
{
var nics = GetAvailableNetworkInterfaces();
if (nics == null) { return new List<HostInfo>(); }
var hosts = new List<HostInfo>();
foreach (NetworkInterface ni in nics)
{
if (supportMulticastOnly && InvalidNIC(ni))
{
continue;
}
//exclude wireshark network interface, it claims it can ping ips lyingly
if (ni.Description.Contains("Npcap")) { continue; }
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
{
var addressBytes = ip.Address.GetAddressBytes();
if (4 == addressBytes.Length && addressBytes[0] == 169 && addressBytes[1] == 254)
{
APILogger.Log($"skipping {ni.Name}\\{ni.Description} as it has a 169.254 address");
continue;//internal only
}
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
{
GetStartAndEndAddress(ip.Address, ip.IPv4Mask, out var startAddress, out var endAddress);
hosts.Add(new HostInfo { HostIpAddress = ip.Address.ToString(), HostNetworkId = ni.Id, HostMacAddress = GetMACAddress(ni.Id),
StartAddress = startAddress, EndAddress = endAddress
});
}
}
}
return hosts;
}
/// <summary>
/// given an IP address and a mask returns a ip address as a string for the first address that is accessible and a string for the last address that is accessible
/// anything between the start address and end address after doing a byte-by-byte comparison should be addressable
/// will return empty strings if something bad happens. Is designed for 4 byte addresses but isn't necessarily limited.
/// </summary>
/// <param name="ip"></param>
/// <param name="mask"></param>
/// <param name="startAddress"></param>
/// <param name="endAddress"></param>
private static void GetStartAndEndAddress( IPAddress ip, IPAddress mask, out string startAddress, out string endAddress)
{
try
{
var ipByte = ip.GetAddressBytes();
var maskBytes = mask.GetAddressBytes();
var startBytes = new byte[ipByte.Length];
var endBytes = new byte[ipByte.Length];
for (var i = 0; i < ipByte.Length; i++)
{
startBytes[i] = (byte)(ipByte[i] & maskBytes[i]);
endBytes[i] = (byte)(ipByte[i] | ~maskBytes[i]);
}
var startIP = new IPAddress(startBytes);
var endIP = new IPAddress(endBytes);
startAddress = startIP.ToString();
endAddress = endIP.ToString();
}
catch( Exception ex)
{
startAddress = string.Empty;
endAddress = string.Empty;
APILogger.Log(ex);
}
}
//FB 25658 Changed the method signature to return bool to determine the connection string has IP in it and it's not USB
/// <summary>
/// Try to parse connectionString and retrieve the IP address.
/// </summary>
/// <param name="connectionString"> DAS connectionString which might include the IP address or might be a USB connection string</param>
/// <param name="ipAddress">Return the parsed IP address from connectionString</param>
/// <returns>Returns true if was able to parse and get the IP otherwise false including the valid USB connection string </returns>
public static bool TryParseConnectionString(string connectionString, out string ipAddress)
{
ipAddress = null;
if (string.IsNullOrEmpty(connectionString))
{
return false;
}
try
{
var uri = new Uri(connectionString);
if (IPAddress.TryParse(uri.Host, out _))
{
ipAddress = uri.Host;
return true;
}
}
catch
{
var ip = connectionString.Split(':')[0];
if (IPAddress.TryParse(ip, out _))
{
ipAddress = ip;
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace DTS.Common.XMLUtils
{
public class DASListXMLClass
{
[XmlElement("DASList")]
public List<DASHardwareXMLClass> DASList {get; set; }
}
}