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,55 @@
using DTS.Common.Utilities.Logging;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
namespace DTS.Common.Classes
{
/// <summary>
/// this is a helper class to avoid performance issues
/// adding or removing a bulk sequence of items from the collection
/// by firing just one notification rather than n
/// </summary>
/// <typeparam name="T"></typeparam>
public class BulkObservableCollection<T> : ObservableCollection<T>
{
public void AddRange(IEnumerable<T> items)
{
try
{
// Turn off notifications (check if anyone is listening first)
CheckReentrancy();
foreach (var item in items) { Items.Add(item); }
// Fire a single notification that the entire "Reset" happened
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Count)));
}
catch( Exception ex)
{
APILogger.Log(ex);
}
}
public void RemoveRange(IEnumerable<T> itemsToRemove)
{
try
{
CheckReentrancy();
foreach (var item in itemsToRemove)
{
Items.Remove(item);
}
// Fire one single notification for the entire operation
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Count)));
}
catch( Exception ex)
{
APILogger.Log(ex);
}
}
}
}

View File

@@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using DTS.Common.Base;
using DTS.Common.Controls;
using DTS.Common.Enums;
using DTS.Common.Enums.Channels;
using DTS.Common.Events;
using DTS.Common.Interface.Channels.ChannelCodes;
using Prism.Events;
using Prism.Ioc;
namespace DTS.Common.Classes.ChannelCodes
{
public class ChannelCode : BasePropertyChanged, IChannelCode
{
//in case this object is held longer before cleanup, make sure code and name are emptied
~ChannelCode()
{
_code = null;
_name = null;
}
private int _id = -1;
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private UIItemStatus _itemStatus = UIItemStatus.None;
public UIItemStatus ItemStatus
{
get => _itemStatus;
set => SetProperty(ref _itemStatus, value, "ItemStatus");
}
protected string _code = string.Empty;
public string Code
{
get => _code;
set => SetProperty(ref _code, value, "Code");
}
protected string _name = string.Empty;
public string Name
{
get => _name;
set => SetProperty(ref _name, value, "Name");
}
public ChannelEnumsAndConstants.ChannelCodeType CodeType { get; set; }
public const string PASTE_ID = "ChannelCode";
// putting a null here avoids wasteful exception that was being thrown during UI construction
// DTM 2020-12-07
public ICommand PasteCommand { get; set; } = null;
public ChannelCode(IDataReader reader, IReadOnlyDictionary<short, string> channelTypeLookup)
{
var codeType = ChannelEnumsAndConstants.ChannelCodeType.User;
var iCodeType = Utility.GetShort(reader, "CodeTypeInt");
if (channelTypeLookup.ContainsKey(iCodeType))
{
var key = channelTypeLookup[iCodeType];
switch (key)
{
case ChannelEnumsAndConstants.UserCodeTypeString:
codeType = ChannelEnumsAndConstants.ChannelCodeType.User;
break;
case ChannelEnumsAndConstants.IsoCodeTypeString:
codeType = ChannelEnumsAndConstants.ChannelCodeType.ISO;
break;
}
}
Id = Utility.GetInt(reader, "Id");
Code = Utility.GetString(reader, "Code");
Name = Utility.GetString(reader, "Name");
CodeType = codeType;
}
public ChannelCode()
{
CodeType = ChannelEnumsAndConstants.ChannelCodeType.ISO;
}
public ChannelCode(IChannelCode channelCode)
{
Id = channelCode.Id;
Code = channelCode.Code;
CodeType = channelCode.CodeType;
Name = channelCode.Name;
}
public override bool Equals(object obj)
{
if (!(obj is ChannelCode other))
{
return false;
}
return Code.Equals(other.Code)
&& Name.Equals(other.Name)
&& CodeType.Equals(other.CodeType);
}
}
public class PasteCommandClass : ICommand
{
public string Id { get; }
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
var eventAggregator = ContainerLocator.Container.Resolve<IEventAggregator>();
try
{
if (!(parameter is TextBox tb))
{
return;
}
if (!(tb.DataContext is IChannelCode channelCode))
{
if (tb.DataContext is ChannelCodeBuilder ccb)
{
channelCode = ccb.DataContext as IChannelCode;
}
else if (tb.DataContext is ChannelNameBuilder cnb)
{
channelCode = cnb.DataContext as IChannelCode;
}
else
{
return;
}
}
if (!Clipboard.ContainsText())
{
return;
}
var text = Clipboard.GetText();
var lines = text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
if (1 == lines.Length)
{
var line = lines[0];
if (line.IndexOfAny(new[] { ',', ';', '\t' }) < 0)
{
//this is a single field paste, don't do any further processing, let textchanged take care of it
eventAggregator.GetEvent<PageModifiedEvent>().Publish(new PageModifiedArg(PageModifiedArg.Status.Modified, null));
return;
}
}
//wipe out the built in effect of the paste
channelCode.Code = channelCode.Code;
channelCode.Name = channelCode.Name;
eventAggregator.GetEvent<TextPastedEvent>().Publish(new TextPastedArgs(text, channelCode, Id, tb.Tag));
}
catch (Exception ex)
{
eventAggregator.GetEvent<PageErrorEvent>().Publish(new PageErrorArg(new[] { ex.Message }, null));
}
}
public event EventHandler CanExecuteChanged;
public PasteCommandClass(string id)
{
Id = id;
}
}
/// <summary>
/// this defines a function to control the behavior of setting an isocode
/// it was done for
/// 14033 finish/clean up from removing CFC filter from digital input on sensor db
/// this allows channels to handle incoming isocodes from the UI and coerce them to a new value
/// </summary>
/// <param name="val"></param>
/// <param name="uniqueISOCodesRequired"></param>
/// <param name="useISOCodeFilterMapping"></param>
/// <returns></returns>
public delegate string CoerceISOCodeDelegate(string val, bool uniqueISOCodesRequired, bool useISOCodeFilterMapping);
}

View File

@@ -0,0 +1,22 @@
using DTS.Common.Events;
using DTS.Common.Interface.Channels.ChannelCodes;
namespace DTS.Common.Classes.ChannelCodes
{
public class TextPastedArgs : ITextPastedEventArgs
{
public string Text { get; }
public object Sender { get; }
public string Id { get; }
public object Tag { get; }
public TextPastedArgs(string text, IChannelCode channelCode, string id, object tag)
{
Text = text;
Sender = channelCode;
Id = id;
Tag = tag;
}
}
}

View File

@@ -0,0 +1,57 @@
using DTS.Common.Classes.DSP;
using System.ComponentModel.DataAnnotations;
using System;
using System.ComponentModel;
namespace DTS.Common.Classes.ClockSync
{
public class ClockSyncProfile : IClockSyncProfile
{
public int ProfileId { get; set; }
public string ProfileName { get; set; }
public string ProfileDesc { get; set; }
public int DisplayOrder { get; set; }
public bool Visible { get; set; }
public DASRestriction[] FilterRestrictions { get; set; }
public ClockSyncProfile() { }
public ClockSyncProfile(int profileId, string profileName, string profileDesc, int displayOrder, bool visible, DASRestriction[] filterRestrictions)
{
Initialize(profileId, profileName, profileDesc, displayOrder, visible, filterRestrictions);
}
public ClockSyncProfile(ClockSyncProfileCollection.ClockSyncProfileDefaults defaults, DASRestriction[] restrictions)
{
GetProfileInfo(defaults, out var displayName, out var description, out var profileId, out var displayOrder, out var visible);
Initialize(profileId, displayName, description, displayOrder, visible, restrictions);
}
private void Initialize(int profileId, string profileName, string profileDesc, int displayOrder, bool visible, DASRestriction[] filterRestrictions)
{
ProfileId = profileId;
ProfileName = profileName;
ProfileDesc = profileDesc;
DisplayOrder = displayOrder;
Visible = visible;
FilterRestrictions = filterRestrictions;
}
private static void GetProfileInfo(ClockSyncProfileCollection.ClockSyncProfileDefaults profile, out string displayName, out string description, out int profileId,
out int displayOrder, out bool visible)
{
profileId = (int)profile;
var enumType = typeof(ClockSyncProfileCollection.ClockSyncProfileDefaults);
var memberInfos = enumType.GetMember(profile.ToString());
var enumValueMemberInfo = Array.Find(memberInfos, m => m.DeclaringType == enumType);
var valueAttributes = enumValueMemberInfo.GetCustomAttributes(typeof(DisplayAttribute), false);
description = ((DisplayAttribute)valueAttributes[0]).GetDescription();
displayName = ((DisplayAttribute)valueAttributes[0]).GetName();
displayOrder = ((DisplayAttribute)valueAttributes[0]).GetOrder() ?? int.MaxValue;
valueAttributes = enumValueMemberInfo.GetCustomAttributes(typeof(BrowsableAttribute), false);
visible = ((BrowsableAttribute)valueAttributes[0]).Browsable;
}
public override string ToString()
{
return ProfileName;
}
}
}

View File

@@ -0,0 +1,120 @@
using DTS.Common.Classes.DSP;
using DTS.Common.Enums.Hardware;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;
namespace DTS.Common.Classes.ClockSync
{
/// <summary>
/// collection for all dsp filters
/// </summary>
public class ClockSyncProfileCollection : Collection<ClockSyncProfile>
{
private static readonly object MyLock = new object();
private static ClockSyncProfileCollection _instance = null;
public static ClockSyncProfileCollection GetCollection()
{
lock (MyLock)
{
if (null != _instance) { return _instance; }
WriteDefaultFileIfMissing(CLOCKSYNC_PROFILE_XML_FILE);
_instance = ReadFile(CLOCKSYNC_PROFILE_XML_FILE);
}
return _instance;
}
private const string CLOCKSYNC_PROFILE_XML_FILE = "ClockSyncProfiles.xml";
private ClockSyncProfileCollection(ClockSyncProfile[] profiles)
{
foreach (var profile in profiles) { Add(profile); }
}
public ClockSyncProfileCollection() { }
public const string NONE_NAME = "None";
public const string PTPIEEE1588_NAME = "PTP IEEE 1588";
public const string IRIGB1PPS_NAME = "IRIG B + 1PPS";
public const string GPS1PPS_NAME = "GPS + 1PPS";
public const string IRIGB_NAME = "IRIG B";
public const string _1PPS_NAME = "1PPS";
public enum ClockSyncProfileDefaults
{
[Display(Name = NONE_NAME, Description = "No master clock input type - RTC from PC only", Order = 0)]
[Browsable(true)]
None = 0,
[Display(Name = PTPIEEE1588_NAME, Description = "Master clock set using Precision Time Protocol IEEE 1588", Order = 1)]
[Browsable(true)]
PTPIEEE1588 = 1 << 0,
[Display(Name = IRIGB1PPS_NAME, Description = "Master clock set using IRIG B on 1 pulse per second", Order = 2)]
[Browsable(true)]
IRIGB1PPS = 1 << 1,
[Display(Name = GPS1PPS_NAME, Description = "Master clock set using GPS on 1 pulse per second", Order = 3)]
[Browsable(true)]
GPS1PPS = 1 << 2,
[Display(Name = IRIGB_NAME, Description ="Master clock set using IRIG B", Order =4)]
[Browsable(true)]
IRIGB = 1 << 3,
[Display(Name = _1PPS_NAME, Description ="Master clock set using 1 pulse per second", Order = 5)]
[Browsable(true)]
_1PPS = 1 << 4
};
private static ClockSyncProfileCollection CreateDefaultCollection()
{
var list = new List<ClockSyncProfile>
{
new ClockSyncProfile(ClockSyncProfileDefaults.None, new DASRestriction[] { new DASRestriction() }),
new ClockSyncProfile(ClockSyncProfileDefaults.PTPIEEE1588, new DASRestriction []{new DASRestriction() }),
new ClockSyncProfile(ClockSyncProfileDefaults.IRIGB1PPS, new DASRestriction[]{new DASRestriction() }),
new ClockSyncProfile(ClockSyncProfileDefaults.GPS1PPS, new DASRestriction[]{new DASRestriction() }),
new ClockSyncProfile(ClockSyncProfileDefaults.IRIGB, new DASRestriction[]{new DASRestriction() }),
new ClockSyncProfile(ClockSyncProfileDefaults._1PPS, new DASRestriction[]{new DASRestriction() }),
};
var collection = new ClockSyncProfileCollection(list.ToArray());
return collection;
}
private static void WriteDefaultFileIfMissing(string filePath)
{
if (File.Exists(filePath)) { return; }
var collection = CreateDefaultCollection();
var serializer = new XmlSerializer(typeof(ClockSyncProfileCollection));
var settings = new XmlWriterSettings() { Indent = true };
using (var writer = XmlWriter.Create(filePath, settings))
{
serializer.Serialize(writer, collection);
}
}
private static ClockSyncProfileCollection ReadFile(string filePath)
{
var deserializer = new XmlSerializer(typeof(ClockSyncProfileCollection));
using (var fs = new FileStream(filePath, FileMode.Open))
{
var cs = (ClockSyncProfileCollection)deserializer.Deserialize(fs);
return cs;
}
}
/// <summary>
/// returns the matching filter, or None if not found, or if none isn't found then the first entry
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public ClockSyncProfile GetClockSyncProfile(string s)
{
var match = Items.FirstOrDefault(x => x.ProfileName == s);
if (null != match) { return match; }
match = Items.FirstOrDefault(x => x.ProfileId == 0);
if (null != match) { return match; }
return Items[0];
}
}
}

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
namespace DTS.Common.Classes.ClockSync
{
/// <summary>
/// this converter is used for displaying StreamingFilterCollection/array in property grids
/// </summary>
public class ClockSyncProfileConverter : ArrayConverter
{
private ClockSyncProfileCollection _collection = null;
private static readonly object MyLock = new object();
private ClockSyncProfile[] _values = null;
private ClockSyncProfileCollection GetCollection()
{
lock (MyLock)
{
if (null == _collection)
{
_collection = ClockSyncProfileCollection.GetCollection();
}
return _collection;
}
}
public ClockSyncProfile[] Values
{
get
{
lock (MyLock)
{
if (null == _values)
{
var collection = GetCollection();
var list = new List<ClockSyncProfile>();
using (var e = collection.GetEnumerator())
{
while (e.MoveNext())
{
if( null != e.Current && e.Current.Visible)
{
list.Add(e.Current);
}
}
}
list.Sort((x,y) => { return x.DisplayOrder.CompareTo(y.DisplayOrder); });
_values = list.ToArray();
}
}
return _values;
}
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string)) { return true; }
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var result = Array.Find(Values, x => x.ProfileName == (string)value);
if (result != null) { return result; }
return base.ConvertFrom(context, culture, value);
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
var collection = GetCollection();
return new StandardValuesCollection(collection);
}
}
}

View File

@@ -0,0 +1,14 @@
using DTS.Common.Classes.DSP;
namespace DTS.Common.Classes.ClockSync
{
public interface IClockSyncProfile
{
int ProfileId { get; set; }
string ProfileName { get; set; }
string ProfileDesc { get; set; }
int DisplayOrder { get; set; }
bool Visible { get; set; }
DASRestriction[] FilterRestrictions { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
using System;
namespace DTS.Common.Classes.Connection
{
public class NotConnectedException : ApplicationException
{
public NotConnectedException(string message)
: base(message)
{
}
}
}

View File

@@ -0,0 +1,80 @@
using DTS.Common.Interface.DASFactory.Diagnostics;
using System;
namespace DTS.Common.Classes.DASFactory
{
public class CanDiagnostics : Base.BasePropertyChanged, ICanDiagnosticResult
{
private bool _Active = false;
public bool Active
{
get => _Active;
set => SetProperty(ref _Active, value);
}
private int _ChannelIndex = -1;
public int ChannelIndex
{
get => _ChannelIndex;
set => SetProperty(ref _ChannelIndex, value);
}
private int _Data = 0;
public int Data
{
get => _Data;
set => SetProperty(ref _Data, value);
}
private int _ErrorFrame = 0;
public int ErrorFrame
{
get => _ErrorFrame;
set
{
SetProperty(ref _ErrorFrame, value);
OnPropertyChanged("Errors");
}
}
private double _Load;
public double Load
{
get => _Load;
set => SetProperty(ref _Load, value);
}
private int _Overruns = 0;
public int Overruns
{
get => _Overruns;
set
{
SetProperty(ref _Overruns, value);
OnPropertyChanged("Errors");
}
}
private DateTime _LastUpdate = DateTime.MinValue;
public DateTime LastUpdate
{
get => _LastUpdate;
set => SetProperty(ref _LastUpdate, value);
}
public int Errors
{
get => _ErrorFrame != 0 ? 1 + Overruns : Overruns;
}
private string _ChannelName = string.Empty;
public string ChannelName
{
get => _ChannelName;
set => SetProperty(ref _ChannelName, value);
}
public void Copy(ICanDiagnosticResult source)
{
Active = source.Active;
ChannelIndex = source.ChannelIndex;
Data = source.Data;
ErrorFrame = source.ErrorFrame;
Load = source.Load;
Overruns = source.Overruns;
LastUpdate = source.LastUpdate;
ChannelName = source.ChannelName;
}
}
}

View File

@@ -0,0 +1,22 @@
namespace DTS.Common.Classes.DASFactory
{
/// <summary>
/// currently used to hold CAN BIST rows - we may expand this to other hardware in future
/// </summary>
public class DiagnosticMessageRow
{
public string Field { get; set; }
public string Value { get; set; }
public string Verdict { get; set; }
public DiagnosticMessageRow(string field, string value, string verdict)
{
Field = field;
Value = value;
Verdict = verdict;
}
public override string ToString()
{
return $"Field: {Field}, Value: {Value}, Verdict: {Verdict}";
}
}
}

View File

@@ -0,0 +1,45 @@
using DTS.Common.Interface.DASFactory.Diagnostics;
using DTS.Common.Interface.Sensors.AnalogDiagnostics;
namespace DTS.Common.Classes.DASFactory
{
public class TCDiagnosticResult : Base.BasePropertyChanged, ITCDiagnosticResult
{
private string _channelName = string.Empty;
public string ChannelName
{
get => _channelName;
set => SetProperty(ref _channelName, value);
}
private int _channelIndex;
public int ChannelIndex
{
get => _channelIndex;
set => SetProperty(ref _channelIndex, value);
}
private double? _currentReading = null;
public double? CurrentReading { get => _currentReading; set => SetProperty(ref _currentReading, value); }
private DiagnosticStatus _status = DiagnosticStatus.Untested;
public DiagnosticStatus Status
{
get => _status;
set => SetProperty(ref _status, value);
}
private ConnectionStatuses _connectionStatus = ConnectionStatuses.NotTested;
public ConnectionStatuses ConnectionStatus
{
get => _connectionStatus;
set => SetProperty(ref _connectionStatus, value);
}
public void Copy(ITCDiagnosticResult source)
{
ChannelName = source.ChannelName;
CurrentReading = source.CurrentReading;
Status = source.Status;
ConnectionStatus = source.ConnectionStatus;
}
}
}

View File

@@ -0,0 +1,242 @@
using DTS.Common.Enums;
using System;
using System.Linq;
using System.Text;
namespace DTS.Common.Classes.DASFactory
{
/// <summary>
/// this class encapsulates/replaces a uint array that was already in use in FWTU and DP
/// it adds some named fields and some to and from just to make things a little easier
/// </summary>
public class TMNSConfig
{
/// <summary>
/// the TMNS config implementation in firmware is just an array of uint32, so here's the same thing internally
/// </summary>
private uint[] _values;
/// <summary>
/// the TMNS PCM sub frame id
/// </summary>
public uint TMNS_PCMSubFrameId
{
get => GetValue(Fields.TMNS_PCMSubFrameID);
set => SetValue(Fields.TMNS_PCMSubFrameID, value);
}
/// <summary>
/// the TMNS message id
/// </summary>
public uint TMNS_MsgId
{
get => GetValue(Fields.TMNS_MsgId);
set => SetValue(Fields.TMNS_MsgId, value);
}
/// <summary>
/// the TMNS PCM minor per major setting
/// </summary>
public uint TMNS_PCMMinorPerMajor
{
get => GetValue(Fields.TMNS_PCMMinorPerMajor);
set => SetValue(Fields.TMNS_PCMMinorPerMajor, value);
}
/// <summary>
/// the TMNS TMATs port number setting
/// </summary>
public uint TMNS_TMATSPortNumber
{
get => GetValue(Fields.TMNS_TMATSPortNumber);
set => SetValue(Fields.TMNS_TMATSPortNumber, value);
}
/// <summary>
/// the IENA UDP source port number
/// </summary>
public uint IENAUDP_PortNumber
{
get => GetValue(Fields.IENAUDP_PortNumber);
set => SetValue(Fields.IENAUDP_PortNumber, value);
}
/// <summary>
/// reserved field 5
/// </summary>
public uint TMNS5
{
get => GetValue(Fields.TMNS5);
set => SetValue(Fields.TMNS5, value);
}
/// <summary>
/// reserved field 6
/// </summary>
public uint TMNS6
{
get => GetValue(Fields.TMNS6);
set => SetValue(Fields.TMNS6, value);
}
/// <summary>
/// reserved field 7
/// </summary>
public uint TMNS7
{
get => GetValue(Fields.TMNS7);
set => SetValue(Fields.TMNS7, value);
}
/// <summary>
/// all fields in the TMNS config unit array and their order
/// </summary>
public enum Fields
{
TMNS_PCMSubFrameID,
TMNS_MsgId,
TMNS_PCMMinorPerMajor,
TMNS_TMATSPortNumber,
IENAUDP_PortNumber,
TMNS5,
TMNS6,
TMNS7
}
/// <summary>
/// handles common init from all constructors
/// </summary>
private void CommonInit()
{
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
_values = new uint[fields.Length];
}
/// <summary>
/// constructor that takes an array of uints in the same order as the TMNS config
/// </summary>
/// <param name="parameters"></param>
public TMNSConfig(uint[] parameters)
{
CommonInit();
if (null == parameters) { return; }
for (var i = 0; i < parameters.Length && i < _values.Length; i++)
{
_values[i] = parameters[i];
}
}
/// <summary>
/// constructor that takes an array of uints comma separated (and allows for enclosing () around whole string)
/// </summary>
/// <param name="parameters"></param>
public TMNSConfig(string parameters)
{
CommonInit();
parameters = parameters.Replace("(", "").Replace(")", "");
var tokens = parameters.Split(new[] { ',' });
for (var i = 0; i < tokens.Length && i < _values.Length; i++)
{
if (uint.TryParse(tokens[i], out var temp))
{
_values[i] = temp;
}
}
}
public TMNSConfig()
{
CommonInit();
}
/// <summary>
/// sets indicated field to indicated value
/// </summary>
/// <param name="field"></param>
/// <param name="value"></param>
public void SetValue(Fields field, uint value)
{
_values[(int)field] = value;
}
/// <summary>
/// gets the value from the indicated field
/// </summary>
/// <param name="field"></param>
/// <returns></returns>
public uint GetValue(Fields field) => _values[(int)field];
public uint[] ToUintArray()
{
var copy = new uint[_values.Length];
_values.CopyTo(copy, 0);
return copy;
}
/// <summary>
/// returns a string suitable for storage (x,...n) of the TMNS config
/// </summary>
/// <returns></returns>
public string ToCSVString()
{
var sb = new StringBuilder();
sb.Append("(");
for (var i = 0; i < _values.Length; i++)
{
if (i > 0) { sb.Append(","); }
sb.Append(_values[i]);
}
sb.Append(")");
return sb.ToString();
}
/// <summary>
/// returns true if the profile is a ch10 streaming profile
/// </summary>
/// <param name="profile"></param>
/// <returns></returns>
public static bool IsCh10(UDPStreamProfile profile)
{
switch (profile)
{
case UDPStreamProfile.CH10_MANUAL_CONFIG:
case UDPStreamProfile.CH10_PCM128_MM:
case UDPStreamProfile.CH10_ANALOG:
case UDPStreamProfile.CH10_PCM_STANDARD:
case UDPStreamProfile.CH10_PCM_SUPERCOM:
case UDPStreamProfile.CH10_PCM_128BIT_2HDR:
case UDPStreamProfile.CH10_ANALOG_2HDR:
case UDPStreamProfile.CH10_PCM_STANDARD_2HDR:
case UDPStreamProfile.CH10_PCM_SUPERCOM_2HDR:
return true;
default:
return false;
}
}
/// <summary>
/// returns true if the streaming profile is an IENA profile
/// </summary>
/// <param name="profile"></param>
/// <returns></returns>
public static bool IsIENA(UDPStreamProfile profile)
{
switch (profile)
{
case UDPStreamProfile.IENA_PTYPE_STREAM: return true;
default: return false;
}
}
/// <summary>
/// returns true if the streaming profile is a TMNS profile
/// </summary>
/// <param name="profile"></param>
/// <returns></returns>
public static bool IsTMNS(UDPStreamProfile profile)
{
switch (profile)
{
case UDPStreamProfile.TMNS_PCM_STANDARD:
case UDPStreamProfile.TMNS_PCM_SUPERCOM:
return true;
default: return false;
}
}
/// <summary>
/// returns true if the streaming profile is a UART profile
/// </summary>
/// <param name="profile"></param>
/// <returns></returns>
public static bool IsUART(UDPStreamProfile profile)
{
switch (profile)
{
case UDPStreamProfile.UART_STREAM: return true;
default: return false;
}
}
}
}

View File

@@ -0,0 +1,116 @@
using DTS.Common.Enums.DASFactory;
using System;
using System.Collections;
using System.Collections.Generic;
using static DTS.Common.Enums.DASFactory.DFConstantsAndEnums;
namespace DTS.Common.Classes.DASFactory
{
public class TemperatureConfig
{
public ushort LogEnable { get; set; }
public ushort LogIntervalSec { get; set; }
private BitArray _channels = new BitArray(new[] { 0x00, 0x00 });
public ushort Channels
{
get
{
var bytes = new byte[2];
_channels.CopyTo(bytes, 0);
return BitConverter.ToUInt16(bytes, 0);
}
set
{
var bytes = BitConverter.GetBytes(value);
_channels = new BitArray(bytes);
}
}
public const ushort Reserved = 0;
public bool MCUTemp
{
get => _channels.Get((int)TempLogChannelBits.OnBoardTemp);
set => _channels.Set((int)TempLogChannelBits.OnBoardTemp, value);
}
public bool OnBoardHumidity
{
get => _channels.Get((int)TempLogChannelBits.OnBoardHumidity);
set => _channels.Set((int)TempLogChannelBits.OnBoardHumidity, value);
}
public bool EnvironmentalCh1
{
get => _channels.Get((int)TempLogChannelBits.EnvironmentalCh1);
set => _channels.Set((int)TempLogChannelBits.EnvironmentalCh1, value);
}
public bool EnvironmentalCh2
{
get => _channels.Get((int)TempLogChannelBits.EnvironmentalCh2);
set => _channels.Set((int)TempLogChannelBits.EnvironmentalCh2, value);
}
public bool EnvironmentalCh3
{
get => _channels.Get((int)TempLogChannelBits.EnvironmentalCh3);
set => _channels.Set((int)TempLogChannelBits.EnvironmentalCh3, value);
}
public bool EnvironmentalCh4
{
get => _channels.Get((int)TempLogChannelBits.EnvironmentalCh4);
set => _channels.Set((int)TempLogChannelBits.EnvironmentalCh4, value);
}
public ushort[] ToUShortArray()
{
return new[] { LogEnable, LogIntervalSec, Channels, Reserved };
}
public TemperatureConfig() { }
public TemperatureConfig(ushort[] ushortArray)
{
if (null == ushortArray) { return; }
LogEnable = GetUShort(ushortArray, 0);
LogIntervalSec = GetUShort(ushortArray, 1);
Channels = GetUShort(ushortArray, 2);
}
private ushort GetUShort(ushort[] ushortArray, int position)
{
if (ushortArray.Length > position) { return ushortArray[position]; }
return 0;
}
public int[] GetChannelsArray()
{
var list = new List<int>();
for (var i = 0; i < _channels.Length; i++)
{
if (_channels.Get(i))
{
list.Add(i);
}
}
return list.ToArray();
}
public S6DBDiagnosticChannelList[] GetMeasurementChannels()
{
var list = new List<S6DBDiagnosticChannelList>();
if (MCUTemp) { list.Add(S6DBDiagnosticChannelList.DiagMcuTemperature); }
if (OnBoardHumidity) { list.Add(S6DBDiagnosticChannelList.DiagEnv_1_Humidity); }
if (EnvironmentalCh1) { list.Add(S6DBDiagnosticChannelList.DiagEnv_1_Temperature); }
if (EnvironmentalCh2) { list.Add(S6DBDiagnosticChannelList.DiagEnv_2_Temperature); }
if (EnvironmentalCh3) { list.Add(S6DBDiagnosticChannelList.DiagEnv_3_Temperature); }
if (EnvironmentalCh4) { list.Add(S6DBDiagnosticChannelList.DiagEnv_4_Temperature); }
return list.ToArray();
}
private readonly Dictionary<S6DBDiagnosticChannelList, TempLogChannelBits> _diagChannelToTempLogBit = new Dictionary<S6DBDiagnosticChannelList, TempLogChannelBits>()
{
{S6DBDiagnosticChannelList.DiagMcuTemperature, TempLogChannelBits.OnBoardTemp },
{S6DBDiagnosticChannelList.DiagEnv_1_Humidity, TempLogChannelBits.OnBoardHumidity },
{S6DBDiagnosticChannelList.DiagEnv_1_Temperature, TempLogChannelBits.EnvironmentalCh1 },
{S6DBDiagnosticChannelList.DiagEnv_2_Temperature, TempLogChannelBits.EnvironmentalCh2 },
{S6DBDiagnosticChannelList.DiagEnv_3_Temperature, TempLogChannelBits.EnvironmentalCh3 },
{S6DBDiagnosticChannelList.DiagEnv_4_Temperature, TempLogChannelBits.EnvironmentalCh4 }
};
public TempLogChannelBits GetChannelBitForDiagChannel(S6DBDiagnosticChannelList ch)
{
if (_diagChannelToTempLogBit.ContainsKey(ch)) { return _diagChannelToTempLogBit[ch]; }
throw new NullReferenceException($"Not found: {ch}");
}
}
}

View File

@@ -0,0 +1,31 @@
namespace DTS.Common.Classes.DSP
{
/// <summary>
/// this is a restriction on who can use this filter
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S101:Types should be named in PascalCase", Justification = "Acronym")]
public class DASRestriction
{
/// <summary>
/// the Hardware_Type string value for the das (e.g. SLICE6_AIR, etc)
/// empty string means all das
/// </summary>
public string DASType { get; set; }
/// <summary>
/// the protocol version for that das (<=0 means all protocol versions will work)
/// </summary>
public int ProtocolVersion { get; set; }
public DASRestriction()
{
DASType = string.Empty;
ProtocolVersion = -1;
}
public DASRestriction(string dasType, int protocolVersion)
{
DASType = dasType;
ProtocolVersion = protocolVersion;
}
}
}

View File

@@ -0,0 +1,115 @@
using DTS.Common.Enums.Hardware;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;
namespace DTS.Common.Classes.DSP
{
/// <summary>
/// collection for all dsp filters
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S101:Types should be named in PascalCase", Justification = "Acronym")]
public class DSPFilterCollection : Collection<DSPFilterType>
{
private static readonly object MyLock = new object();
private static DSPFilterCollection _instance = null;
public static DSPFilterCollection GetDSPFilterCollection()
{
lock (MyLock)
{
if (null != _instance) { return _instance; }
WriteDefaultFileIfMissing(DSP_FILTER_XML_FILE);
_instance = ReadFile(DSP_FILTER_XML_FILE);
}
return _instance;
}
private const string DSP_FILTER_XML_FILE = "DSPFilters.xml";
private DSPFilterCollection(DSPFilterType[] filters)
{
foreach (var filter in filters) { Add(filter); }
}
public DSPFilterCollection() { }
public const int BUTTERWORTH = 13;
public const int FIR45TAP = 14;
public const int NONE = 0;
public enum DSPFilterDefaults
{
[Display(Name ="None", Description = "Default and legacy setting for streaming")]
[Scaler(double.NaN)]
None = NONE,
[Display(Name = "6th IIR Butterworth", Description = "6 - pole IIR Butterworth Low Pass")]
[Scaler(double.NaN)]
Butterworth = BUTTERWORTH,
[Display(Name = "45-Tap FIR", Description = "finite impulse response filter with 45 taps")]
[Scaler(double.NaN)]
FIR = FIR45TAP
}
private static DSPFilterCollection CreateDefaultCollection()
{
var list = new List<DSPFilterType>
{
new DSPFilterType(DSPFilterDefaults.None, new DASRestriction[] { new DASRestriction() }),
new DSPFilterType(DSPFilterDefaults.Butterworth, new DASRestriction[]
{
new DASRestriction(HardwareTypes.SLICE6_AIR.ToString(), 28),
new DASRestriction(HardwareTypes.SLICE6_AIR_BR.ToString(), -1),
new DASRestriction(HardwareTypes.SLICE6_AIR_TC.ToString(), -1)
}),
new DSPFilterType(DSPFilterDefaults.FIR, new DASRestriction[]
{
new DASRestriction(HardwareTypes.SLICE6_AIR.ToString(), 28),
new DASRestriction(HardwareTypes.SLICE6_AIR_BR.ToString(), -1),
new DASRestriction(HardwareTypes.SLICE6_AIR_TC.ToString(), -1)
})
};
var collection = new DSPFilterCollection(list.ToArray());
return collection;
}
private static void WriteDefaultFileIfMissing(string filePath)
{
if (File.Exists(filePath)) { return; }
var collection = CreateDefaultCollection();
var serializer = new XmlSerializer(typeof(DSPFilterCollection));
var settings = new XmlWriterSettings() { Indent = true };
using (var writer = XmlWriter.Create(filePath, settings))
{
serializer.Serialize(writer, collection);
}
}
private static DSPFilterCollection ReadFile(string filePath)
{
var deserializer = new XmlSerializer(typeof(DSPFilterCollection));
using (var fs = new FileStream(filePath, FileMode.Open))
{
var cs = (DSPFilterCollection)deserializer.Deserialize(fs);
return cs;
}
}
/// <summary>
/// returns the matching filter, or None if not found, or if none isn't found then the first entry
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public DSPFilterType GetFilter(string s)
{
var match = Items.FirstOrDefault(x => x.DisplayString == s);
if (null != match) { return match; }
match = Items.FirstOrDefault(x => x.EnumValue == 0);
if (null != match) { return match; }
return Items[0];
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.ComponentModel;
using System.Globalization;
namespace DTS.Common.Classes.DSP
{
/// <summary>
/// this converter is used to display DSPFilterCollection in a property grid
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S101:Types should be named in PascalCase", Justification = "Acronym")]
public class DSPFilterConverter : ArrayConverter
{
private DSPFilterCollection _collection = null;
private static readonly object MyLock = new object();
private DSPFilterType[] _values = null;
private DSPFilterCollection GetCollection()
{
lock (MyLock)
{
if (null == _collection)
{
_collection = DSPFilterCollection.GetDSPFilterCollection();
}
return _collection;
}
}
public DSPFilterType [] Values
{
get
{
lock (MyLock)
{
if (null == _values)
{
var collection = GetCollection();
var array = new DSPFilterType[collection.Count];
collection.CopyTo(array, 0);
_values = array;
}
}
return _values;
}
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string)) { return true; }
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var result = Array.Find(Values, x => x.DisplayString == (string)value);
if (result != null) { return result; }
return base.ConvertFrom(context, culture, value);
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
var collection = GetCollection();
return new StandardValuesCollection(collection);
}
}
}

View File

@@ -0,0 +1,31 @@
namespace DTS.Common.Classes.DSP
{
/// <summary>
/// this is a restriction on who can use this filter
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S101:Types should be named in PascalCase", Justification = "Acronym")]
public class DSPFilterRestriction
{
/// <summary>
/// the Hardware_Type string value for the das (e.g. SLICE6_AIR, etc)
/// empty string means all das
/// </summary>
public string DASType { get; set; }
/// <summary>
/// the protocol version for that das (<=0 means all protocol versions will work)
/// </summary>
public int ProtocolVersion { get; set; }
public DSPFilterRestriction()
{
DASType = string.Empty;
ProtocolVersion = -1;
}
public DSPFilterRestriction(string dasType, int protocolVersion)
{
DASType = dasType;
ProtocolVersion = protocolVersion;
}
}
}

View File

@@ -0,0 +1,121 @@
using DTS.Common.Enums.Hardware;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace DTS.Common.Classes.DSP
{
/// <summary>
/// see IStreamingFilterProfile for more information
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S101:Types should be named in PascalCase", Justification = "Acronym")]
public class DSPFilterType : IStreamingFilterProfile
{
public double Ratio { get; set; }
public int EnumValue { get; set; }
public string DisplayString { get; set; }
public string DescriptionString { get; set; }
private readonly List<DASRestriction> _restrictions = new List<DASRestriction>();
public DASRestriction[] Restrictions { get => _restrictions.ToArray(); set { _restrictions.Clear(); _restrictions.AddRange(value); } }
public DSPFilterType() { }
public DSPFilterType(DSPFilterCollection.DSPFilterDefaults filter, DASRestriction[] restrictions)
{
GetProfileValues(filter, out var displayName, out var description, out var enumValue, out var ratio);
Initialize(enumValue, displayName, description, ratio, restrictions);
}
public DSPFilterType(int enumValue, string displayString, string descriptionString, double ratio, DASRestriction[] restrictions)
{
Initialize(enumValue, displayString, descriptionString, ratio, restrictions);
}
private void Initialize(int enumValue, string displayString, string descriptionString, double ratio, DASRestriction[] restrictions)
{
EnumValue = enumValue;
DisplayString = displayString;
DescriptionString = descriptionString;
Restrictions = restrictions;
Ratio = ratio;
}
public override string ToString()
{
return DisplayString;
}
public static void GetProfileValues(DSPFilterCollection.DSPFilterDefaults filter, out string displayName, out string description, out int enumValue,
out double ratio)
{
displayName = string.Empty;
description = string.Empty;
enumValue = -1;
ratio = -1;
var enumType = typeof(DSPFilterCollection.DSPFilterDefaults);
var memberInfos = enumType.GetMember(filter.ToString());
var enumValueMemberInfo = Array.Find(memberInfos, m => m.DeclaringType == enumType);
var valueAttributes = enumValueMemberInfo.GetCustomAttributes(typeof(DisplayAttribute), false);
enumValue = (int)filter;
description = ((DisplayAttribute)valueAttributes[0]).GetDescription();
displayName = ((DisplayAttribute)valueAttributes[0]).GetName();
valueAttributes = enumValueMemberInfo.GetCustomAttributes(typeof(ScalerAttribute), false);
ratio = ((ScalerAttribute)valueAttributes[0]).Scaler;
}
/// <summary>
/// this is the table of breakpoints and corresponding fC for S6A/br
/// </summary>
private static readonly List<Tuple<int, int>> _6PButterWorthTable = new List<Tuple<int, int>>
(
new[]
{
new Tuple<int,int>(8000, 1280),
new Tuple<int,int>(5000, 610),
new Tuple<int,int>(2000, 366),
new Tuple<int,int>(1000, 120),
new Tuple<int,int>(500,120),
new Tuple<int,int>(200,50),
new Tuple<int,int>(80,15)
}
);
/// <summary>
/// returns an array of breakpoints and fC for S6A and S6A-BR legacy butterworth digital filter
/// </summary>
/// <returns></returns>
public static Tuple<int, int>[] Get6PButterWorthLegacyTable() { return _6PButterWorthTable.ToArray(); }
/// <summary>
/// this is the cap of SPS where S6A will fall back on AAF
/// </summary>
public const int S6A_CAP = 20480;
/// <summary>
/// returns the fC given a hardware type, and the legacy 6P butterworth filter
/// double.NaN means the filter is not supported
/// </summary>
/// <param name="sps"></param>
/// <param name="hwType"></param>
/// <returns></returns>
public static double GetLegacytDSPFilterRate(double sps, string hwType)
{
//if we have legacy then we need the sample rate, if it's >8k s6abr then Fc
if (hwType == HardwareTypes.SLICE6_AIR.ToString() && sps >= S6A_CAP) { return double.NaN; }
var array = Get6PButterWorthLegacyTable();
Array.Sort(array, (x, y) => { return y.Item1.CompareTo(x.Item1); });
foreach (var entry in array)
{
if (sps >= entry.Item1) { return entry.Item2; }
}
return double.NaN;
}
/// <summary>
/// returns a filter rate given the current digital filter profile and sps and hardware type
/// </summary>
/// <param name="sps"></param>
/// <param name="hwType"></param>
/// <returns></returns>
public double GetDSPFilterRate(double sps, string hwType)
{
if (EnumValue != DSPFilterCollection.BUTTERWORTH) { return double.NaN; }
if (!Array.Exists(Restrictions, x => x.DASType == hwType || string.IsNullOrEmpty(x.DASType))) { return double.NaN; }
return GetLegacytDSPFilterRate(sps, hwType);
}
}
}

View File

@@ -0,0 +1,34 @@
namespace DTS.Common.Classes.DSP
{
public interface IStreamingFilterProfile
{
/// <summary>
/// the byte/enum value to send to the firmware for this filter type
/// </summary>
int EnumValue { get; set; }
/// <summary>
/// the display string for this filter
/// </summary>
string DisplayString { get; set; }
/// <summary>
/// description string for this filter
/// </summary>
string DescriptionString { get; set; }
/// <summary>
/// any restrictions on what das can use this filter
/// </summary>
DASRestriction[] Restrictions { get; set; }
/// <summary>
/// if this profile uses a ratio, then the ratio of sps to fC
/// </summary>
double Ratio { get; set; }
/// <summary>
/// returns the fC given the hardware type and the sample rate
/// returns null if digital filtering isn't used in this combination
/// </summary>
/// <param name="sps"></param>
/// <param name="hwType"></param>
/// <returns></returns>
double GetDSPFilterRate(double sps, string hwType);
}
}

View File

@@ -0,0 +1,18 @@
using System;
namespace DTS.Common.Classes.DSP
{
/// <summary>
/// generic attribute to store doubles, so for say scalers or ratios
/// </summary>
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field, AllowMultiple = false)]
public class ScalerAttribute : Attribute
{
public double Scaler { get; set; }
public ScalerAttribute(double d)
{
Scaler = d;
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.ComponentModel;
using System.Globalization;
namespace DTS.Common.Classes.DSP
{
/// <summary>
/// this converter is used for displaying StreamingFilterCollection/array in property grids
/// </summary>
public class StreamingFilterConverter : ArrayConverter
{
private StreamingFilterProfileCollection _collection = null;
private static readonly object MyLock = new object();
private StreamingFilterProfile[] _values = null;
private StreamingFilterProfileCollection GetCollection()
{
lock (MyLock)
{
if (null == _collection)
{
_collection = StreamingFilterProfileCollection.GetCollection();
}
return _collection;
}
}
public StreamingFilterProfile[] Values
{
get
{
lock (MyLock)
{
if (null == _values)
{
var collection = GetCollection();
var array = new StreamingFilterProfile[collection.Count];
collection.CopyTo(array, 0);
_values = array;
}
}
return _values;
}
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string)) { return true; }
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var result = Array.Find(Values, x => x.DisplayString == (string)value);
if (result != null) { return result; }
return base.ConvertFrom(context, culture, value);
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
var collection = GetCollection();
return new StandardValuesCollection(collection);
}
}
}

View File

@@ -0,0 +1,82 @@
using DTS.Common.Enums.Hardware;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace DTS.Common.Classes.DSP
{
public class StreamingFilterProfile : IStreamingFilterProfile
{
public double Ratio { get; set; }
public string DisplayString { get; set; }
public string DescriptionString { get; set; }
public int EnumValue { get; set; }
private readonly List<DASRestriction> _restrictions = new List<DASRestriction>();
public DASRestriction[] Restrictions { get => _restrictions.ToArray(); set { _restrictions.Clear(); _restrictions.AddRange(value); } }
public StreamingFilterProfile() { }
public StreamingFilterProfile(StreamingFilterProfileCollection.DefaultProfiles profile, DASRestriction[] restrictions)
{
GetProfileValues(profile, out var displayName, out var description, out var enumValue, out var ratio);
Initialize(displayName, description, enumValue, ratio, restrictions);
}
public StreamingFilterProfile(string display, string description, int enumValue, double ratio, DASRestriction[] restrictions)
{
Initialize(display, description, enumValue, ratio, restrictions);
}
private void Initialize(string display, string description, int enumValue, double ratio, DASRestriction[] restrictions)
{
DisplayString = display;
DescriptionString = description;
EnumValue = enumValue;
Restrictions = restrictions;
Ratio = ratio;
}
public override string ToString()
{
return DisplayString;
}
public static void GetProfileValues(StreamingFilterProfileCollection.DefaultProfiles profile, out string displayName, out string description, out int enumValue,
out double ratio)
{
displayName = string.Empty;
description = string.Empty;
enumValue = -1;
ratio = -1;
var enumType = typeof(StreamingFilterProfileCollection.DefaultProfiles);
var memberInfos = enumType.GetMember(profile.ToString());
var enumValueMemberInfo = Array.Find(memberInfos, m => m.DeclaringType == enumType);
var valueAttributes = enumValueMemberInfo.GetCustomAttributes(typeof(DisplayAttribute), false);
enumValue = (int)profile;
description = ((DisplayAttribute)valueAttributes[0]).GetDescription();
displayName = ((DisplayAttribute)valueAttributes[0]).GetName();
valueAttributes = enumValueMemberInfo.GetCustomAttributes(typeof(ScalerAttribute), false);
ratio = ((ScalerAttribute)valueAttributes[0]).Scaler;
}
public double GetDSPFilterRate(double sps, string hwType)
{
//if we have legacy then we need the sample rate, if it's >8k s6abr then Fc
if (hwType == HardwareTypes.SLICE6_AIR.ToString() && sps >= DSPFilterType.S6A_CAP) { return double.NaN; }
if (!Array.Exists(Restrictions, x => x.DASType == hwType || string.IsNullOrEmpty(x.DASType))) { return double.NaN; }
if (EnumValue == StreamingFilterProfileCollection.DEFAULT_VALUE)
{
return DSPFilterType.GetLegacytDSPFilterRate(sps, hwType);
}
else if (double.IsNaN(Ratio)) { return double.NaN; }
var array = DSPFilterType.Get6PButterWorthLegacyTable();
Array.Sort(array, (x, y) => { return y.Item1.CompareTo(x.Item1); });
foreach (var entry in array)
{
if (sps >= entry.Item1) { return sps / Ratio; }
}
return double.NaN;
}
}
}

View File

@@ -0,0 +1,116 @@
using DTS.Common.Enums.Hardware;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;
namespace DTS.Common.Classes.DSP
{
public class StreamingFilterProfileCollection : Collection<StreamingFilterProfile>
{
private static readonly object MyLock = new object();
private static StreamingFilterProfileCollection _instance = null;
public static StreamingFilterProfileCollection GetCollection()
{
lock (MyLock)
{
if (null != _instance) { return _instance; }
WriteDefaultFileIfMissing(FILTER_PROFILES_XML_FILE);
_instance = ReadFile(FILTER_PROFILES_XML_FILE);
}
return _instance;
}
private const string FILTER_PROFILES_XML_FILE = "StreamingFilterProfiles.xml";
private StreamingFilterProfileCollection(StreamingFilterProfile[] filters)
{
foreach (var filter in filters) { Add(filter); }
}
public StreamingFilterProfileCollection() { }
public enum DefaultProfiles
{
[Display(Name ="Default (Mixed)", Description = "6 pole butterworth legacy or default", Order = DEFAULT_VALUE)]
[Scaler(double.NaN)]
Default = DEFAULT_VALUE,
[Display(Name ="Sample rate / 4", Description = "based on sample rate")]
[Scaler(4)]
Profile7 = 7,
[Display(Name = "Sample rate / 6.4", Description = "based on sample rate")]
[Scaler(6.4)]
Profile8 = 8,
[Display(Name = "Sample rate / 8", Description = "based on sample rate")]
[Scaler(8)]
Profile9 = 9,
[Display(Name = "Sample rate / 10", Description = "based on sample rate")]
[Scaler(10)]
Profile10 = 10
}
private static StreamingFilterProfileCollection CreateDefaultCollection()
{
var list = new List<StreamingFilterProfile>
{
new StreamingFilterProfile(DefaultProfiles.Default, new[] { new DASRestriction(string.Empty, -1) }),
new StreamingFilterProfile(DefaultProfiles.Profile7, new[]
{
new DASRestriction(HardwareTypes.SLICE6_AIR_BR.ToString(), 50), new DASRestriction(HardwareTypes.SLICE6_AIR.ToString(), 51), new DASRestriction(HardwareTypes.SLICE6_AIR_TC.ToString(), 0)
}),
new StreamingFilterProfile(DefaultProfiles.Profile8, new[]
{
new DASRestriction(HardwareTypes.SLICE6_AIR_BR.ToString(), 50), new DASRestriction(HardwareTypes.SLICE6_AIR.ToString(), 51), new DASRestriction(HardwareTypes.SLICE6_AIR_TC.ToString(), 0)
}),
new StreamingFilterProfile(DefaultProfiles.Profile9, new[]
{
new DASRestriction(HardwareTypes.SLICE6_AIR_BR.ToString(), 50), new DASRestriction(HardwareTypes.SLICE6_AIR.ToString(), 51), new DASRestriction(HardwareTypes.SLICE6_AIR_TC.ToString(), 0)
}),
new StreamingFilterProfile(DefaultProfiles.Profile10, new[]
{
new DASRestriction(HardwareTypes.SLICE6_AIR_BR.ToString(), 50), new DASRestriction(HardwareTypes.SLICE6_AIR.ToString(), 51), new DASRestriction(HardwareTypes.SLICE6_AIR_TC.ToString(), 0)
})
};
var collection = new StreamingFilterProfileCollection(list.ToArray());
return collection;
}
private static void WriteDefaultFileIfMissing(string filePath)
{
if (File.Exists(filePath)) { return; }
var collection = CreateDefaultCollection();
var serializer = new XmlSerializer(typeof(StreamingFilterProfileCollection));
var settings = new XmlWriterSettings() { Indent = true };
using (var writer = XmlWriter.Create(filePath, settings))
{
serializer.Serialize(writer, collection);
}
}
private static StreamingFilterProfileCollection ReadFile(string filePath)
{
var deserializer = new XmlSerializer(typeof(StreamingFilterProfileCollection));
using (var fs = new FileStream(filePath, FileMode.Open))
{
var cs = (StreamingFilterProfileCollection)deserializer.Deserialize(fs);
return cs;
}
}
public const int DEFAULT_VALUE = 13;
public StreamingFilterProfile GetStreamingFilterProfile(string s)
{
var match = Items.FirstOrDefault(x => x.DisplayString == s);
if (null != match) { return match; }
match = Items.FirstOrDefault(x => x.EnumValue == DEFAULT_VALUE);
if (null != match) { return match; }
return Items[0];
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Windows.Input;
namespace DTS.Common.Classes.Viewer.Commands
{
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute ?? throw new ArgumentNullException("execute");
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
public bool CanExecute(object parameter)
{
return _canExecute?.Invoke(parameter) ?? true;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
}

View File

@@ -0,0 +1,18 @@
using DTS.Common.Interface;
using System.ComponentModel;
namespace DTS.Common.Classes.Viewer.Reports
{
public class ChannelGRMSSummary : IChannelGRMSSummary
{
public string ChannelName { get; set; }
public int SampleRate { get; set; }
public double GRMS { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,445 @@
using System;
using System.Linq;
using System.Windows.Media;
using DTS.Common.Base;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface;
// ReSharper disable CheckNamespace
// ReSharper disable RedundantDefaultMemberInitializer
// ReSharper disable RedundantCast
namespace DTS.Common.Classes.Viewer.TestMetadata
{
[Serializable]
public class TestChannel : BasePropertyChanged, ITestChannel
{
public string Group { get; set; }
public string SubGroup { get; set; }
private bool _isGraphChannel = false;
public bool IsGraphChannel { get => _isGraphChannel; set { _isGraphChannel = value; OnPropertyChanged("IsGraphChannel"); } }
public string GraphName { get; set; }
public string TestId { get; set; }
public string TestSetupName { get; set; }
public string ModuleSerialNumber { get; set; }
public string SerialNumber { get; set; }
public string ChannelId { get; set; }
private string _channelDisplayName = string.Empty;
public string ChannelDisplayName
{
get => _channelDisplayName;
set => SetProperty(ref _channelDisplayName, value, "ChannelDisplayName");
}
public string Description { get; set; }
public string IsoCode { get; set; }
public string IsoChannelName { get; set; }
public string UserCode { get; set; }
public string UserChannelName { get; set; }
public string ChannelGroupName { get; set; }
public string ChannelType { get; set; }
private bool _isCalculatedChannel = false;
public bool IsCalculatedChannel
{
get => _isCalculatedChannel;
set => SetProperty(ref _isCalculatedChannel, value, "IsCalculatedChannel");
}
public int Number { get; set; }
public string DigitalMultiplier { get; set; }
public string DigitalMode { get; set; }
public DateTime Start { get; set; }
public string Bridge { get; set; }
public double BridgeResistanceOhms { get; set; }
public double ZeroPoint { get; set; }
private string _channelDescriptionString;
public ulong T1Sample { get; set; } = 0;
public ulong T2Sample { get; set; } = 0;
public double HIC { get; set; } = 0D;
public bool UseEUScaler { get; set; }
public double ScaleFactorEU { get; set; } = 0D;
public string ChannelDescriptionString
{
get => _channelDescriptionString;
set => SetProperty(ref _channelDescriptionString, value, "ChannelDescriptionString");
}
public void SetChannelDescriptionAndDisplayName(string channelDescription)
{
ChannelDescriptionString = channelDescription;
ChannelDisplayName = $"{ChannelName2} {ChannelDescriptionString}";
}
public string ChannelName2 { get; set; }
public string HardwareChannelName { get; set; }
public double DesiredRange { get; set; }
public double ActualMaxRangeEu { get; set; }
public double ActualMinRangeEu { get; set; }
public double ActualMaxRangeAdc => short.MaxValue;
public double ActualMinRangeAdc => short.MinValue;
public double ActualMaxRangeMv { get; set; }
public double ActualMinRangeMv { get; set; }
public double Sensitivity { get; set; }
public string SoftwareFilter { get; set; }
public bool ProportionalToExcitation { get; set; }
public bool IsInverted { get; set; }
public string LinearizationFormula { get; set; }
public bool IsSubsampled { get; set; }
public int AbsoluteDisplayOrder { get; set; }
public DateTime LastCalibrationDate { get; set; }
public string SensorId { get; set; }
public int OffsetToleranceLowMv { get; set; }
public int OffsetToleranceHighMv { get; set; }
public int DataFlag { get; set; }
public string ExcitationVoltage { get; set; }
public string Eu { get; set; }
public bool CalSignalEnabled { get; set; }
public bool ShuntEnabled { get; set; }
public bool VoltageInsertionCheckEnabled { get; set; }
public bool RemoveOffset { get; set; }
public string ZeroMethod { get; set; }
public double ZeroAverageWindowBegin { get; set; }
public double ZeroAverageWindowEnd { get; set; }
public int InitialEu { get; set; }
public string InitialOffset { get; set; }
public int UnsubsampledSampleRateHz { get; set; }
public double MeasuredShuntDeflectionMv { get; set; }
public double TargetShuntDeflectionMv { get; set; }
public double MeasuredExcitationVoltage { get; set; }
public double FactoryExcitationVoltage { get; set; }
public double TimeOfFirstSample { get; set; }
public double Multiplier { get; set; }
public double UserOffsetEu { get; set; }
public int UnitConversion { get; set; }
public bool AtCapacity { get; set; }
public int CapacityOutputIsBasedOn { get; set; }
public string SourceChannelNumber { get; set; }
public string SourceModuleNumber { get; set; }
public string SourceModuleSerialNumber { get; set; }
public string Calculation { get; set; }
public int SampleRateHz { get; set; }
public string SensitivityUnits { get; set; }
public int SensorCapacity { get; set; }
public string SensorPolarity { get; set; }
public int ChannelNumber { get; set; }
public string BinaryFileName { get; set; }
public string BinaryFilePath { get; set; }
public double Xmax { get; set; }
public double Xmin { get; set; }
public int SequentialNumbers { get; set; }
public ITestSetupMetadata ParentTestSetup { get; set; }
public ITestModule ParentModule { get; set; }
public IBaseViewModel Parent { get; set; }
private Color _channelColor = Colors.Transparent;
public Color ChannelColor
{
get => _channelColor;
set => SetProperty(ref _channelColor, value, "ChannelColor");
}
private string _errorMessage = string.Empty;
public string ErrorMessage
{
get => _errorMessage;
set
{
_errorMessage = value;
_isError = !string.IsNullOrEmpty(_errorMessage);
OnPropertyChanged("ErrorMessage");
}
}
private bool _isError = false;
public bool IsError
{
get => _isError;
set => SetProperty(ref _isError, value, "IsError");
}
private Color? _errorColor = Colors.Black;
public Color? ErrorColor
{
get { _errorColor = _isError ? Colors.Red : Colors.Black; return _errorColor; }
set => SetProperty(ref _errorColor, value, "ErrorColor");
}
private bool _isLocked = false;
public bool IsLocked
{
get => _isLocked;
set
{
_isLocked = value;
if (!_isLocked && !_isSelected && !_isGraphChannel) { ChannelColor = Colors.Transparent; }
if (CanSelectChannel)
{
var parent = Parent;
if (parent.GetType().GetInterfaces().Contains(typeof(IGraphMainViewModel))) { ((IGraphMainViewModel)parent).AddLockedChannel(this, _isLocked); }
}
OnPropertyChanged("IsLocked");
}
}
private bool _bCanLock = true;
public bool CanLock
{
get => _bCanLock;
set => SetProperty(ref _bCanLock, !IsError && value, "CanLock");
}
private bool _canSelectChannel = true;
public bool CanSelectChannel
{
get => _canSelectChannel;
set => SetProperty(ref _canSelectChannel, !IsError && value, "CanSelectChannel");
}
private bool _isExpanded = true;
public bool IsExpanded
{
get => _isExpanded;
set => SetProperty(ref _isExpanded, value, "IsExpanded");
}
private bool _isSelected = false;
public bool IsSelected
{
get => _isSelected;
set
{
var parent = Parent;
_isSelected = value;
if (!_isLocked && !_isSelected && !_isGraphChannel) { ChannelColor = Colors.Transparent; }
if (_isSelected && CanSelectChannel)
{
if (parent.GetType().GetInterfaces().Contains(typeof(IGraphMainViewModel))) { ((IGraphMainViewModel)parent).AddSelectedChannel(this); }
OnPropertyChanged("IsSelected");
}
}
}
public ITestChannel Copy() { return (TestChannel)MemberwiseClone(); }
public override string ToString()
{
if (SensorConstants.IsTestSpecificEmbedded(ChannelDescriptionString) && !string.IsNullOrWhiteSpace(ChannelName2)) { return ChannelName2; }
return ChannelDescriptionString;
}
private double _minADC = double.NaN;
/// <summary>
/// Min value of ADC for entire dataset
/// </summary>
public double MinADC
{
get => _minADC;
set => SetProperty(ref _minADC, value, "MinADC");
}
private double _maxADC = double.NaN;
/// <summary>
/// Max value in ADC for entire dataset
/// </summary>
public double MaxADC
{
get => _maxADC;
set => SetProperty(ref _maxADC, value, "MaxADC");
}
private double _aveADC = double.NaN;
/// <summary>
/// Average value in ADC for entire dataset
/// </summary>
public double AveADC
{
get => _aveADC;
set => SetProperty(ref _aveADC, value, "AveADC");
}
private double _stdDevADC = double.NaN;
/// <summary>
/// STD DEV in ADC for entire dataset
/// </summary>
public double StdDevADC
{
get => _stdDevADC;
set => SetProperty(ref _stdDevADC, value, "StdDevADC");
}
private double _t0ADC = double.NaN;
/// <summary>
/// Value @ T0 in ADC
/// </summary>
public double T0ADC
{
get => _t0ADC;
set => SetProperty(ref _t0ADC, value, "T0ADC");
}
private double _minMV = double.NaN;
/// <summary>
/// Minimum value in mV for entire dataset
/// </summary>
public double MinMV
{
get => _minMV;
set => SetProperty(ref _minMV, value, "MinMV");
}
private double _maxMV = double.NaN;
/// <summary>
/// Maximum value in mV for entire dataset
/// </summary>
public double MaxMV
{
get => _maxMV;
set => SetProperty(ref _maxMV, value, "MaxMV");
}
private double _aveMV = double.NaN;
/// <summary>
/// average value in mV for entire dataset
/// </summary>
public double AveMV
{
get => _aveMV;
set => SetProperty(ref _aveMV, value, "AveMV");
}
private double _stdDevMV = double.NaN;
/// <summary>
/// std dev in mV for entire dataset
/// </summary>
public double StdDevMV
{
get => _stdDevMV;
set => SetProperty(ref _stdDevMV, value, "StdDevMV");
}
private double _t0MV = double.NaN;
/// <summary>
/// value in mV at T0
/// </summary>
public double T0MV
{
get => _t0MV;
set => SetProperty(ref _t0MV, value, "T0MV");
}
private double _minEU = double.NaN;
/// <summary>
/// minimum value in EU for entire dataset
/// </summary>
public double MinEU
{
get => _minEU;
set => SetProperty(ref _minEU, value, "MinEU");
}
private double _maxEU = double.NaN;
/// <summary>
/// maximum value in EU for entire dataset
/// </summary>
public double MaxEU
{
get => _maxEU;
set => SetProperty(ref _maxEU, value, "MaxEU");
}
private double _aveEU = double.NaN;
/// <summary>
/// average value in EU for entire dataset
/// </summary>
public double AveEU
{
get => _aveEU;
set => SetProperty(ref _aveEU, value, "AveEU");
}
private double _stdDevEU = double.NaN;
/// <summary>
/// std dev in EU
/// </summary>
public double StdDevEU
{
get => _stdDevEU;
set => SetProperty(ref _stdDevEU, value, "StdDevEU");
}
private double _t0EU = double.NaN;
/// <summary>
/// value at T0 in EU
/// </summary>
public double T0EU
{
get => _t0EU;
set => SetProperty(ref _t0EU, value, "T0EU");
}
private double _minY = double.NaN;
/// <summary>
/// minimum value for whatever current units are for entire dataset
/// </summary>
public double MinY
{
get => _minY;
set => SetProperty(ref _minY, value, "MinY");
}
private double _maxY = double.NaN;
/// <summary>
/// maximum value for whatever current units are for entire dataset
/// </summary>
public double MaxY
{
get => _maxY;
set => SetProperty(ref _maxY, value, "MaxY");
}
private double _aveY = double.NaN;
/// <summary>
/// average value for whatever current units are for entire dataset
/// </summary>
public double AveY
{
get => _aveY;
set => SetProperty(ref _aveY, value, "AveY");
}
private double _stdDevY = double.NaN;
/// <summary>
/// std deviation for whatever current units are
/// </summary>
public double StdDevY
{
get => _stdDevY;
set => SetProperty(ref _stdDevY, value, "StdDevY");
}
private double _T0Value = double.NaN;
/// <summary>
/// Value at T0 in whatever current units are
/// </summary>
public double T0Value
{
get => _T0Value;
set => SetProperty(ref _T0Value, value, "T0Value");
}
private string _setupEID = string.Empty;
/// <summary>
/// EID channel was originally set up with
/// </summary>
public string SetupEID
{
get => _setupEID;
set => SetProperty(ref _setupEID, value, "SetupEID");
}
private string _dataCollectionEID = string.Empty;
/// <summary>
/// EID present on channel when data was collected
/// </summary>
public string DataCollectionEID
{
get => _dataCollectionEID;
set => SetProperty(ref _dataCollectionEID, value, "DataCollectionEID");
}
}
}

View File

@@ -0,0 +1,14 @@
using System.Collections.Generic;
using DTS.Common.Interface;
// ReSharper disable CheckNamespace
namespace DTS.Common.Classes.Viewer.TestMetadata
{
public class TestGraphs : ITestGraphs
{
public string Name { get; set; }
public string HardwareChannelName { get; set; }
public List<string> ChannelIds { get; set; }
public List<ITestChannel> Channels { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
using DTS.Common.Interface;
using DTS.Common.Interface.TestDefinition;
// ReSharper disable CheckNamespace
namespace DTS.Common.Classes.Viewer.TestMetadata
{
public class TestMetadata : ITestMetadata
{
public ITestRunMetadata TestRun { get; set; }
public ITestSetupMetadata TestSetup { get; set; }
}
}

View File

@@ -0,0 +1,694 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;
using DTS.Common.Base;
using DTS.Common.Enums;
using DTS.Common.Enums.Sensors;
using DTS.Common.Enums.Viewer;
using DTS.Common.Interface;
using DTS.Common.Interface.TestDefinition;
using DTS.Common.Utilities;
using DTS.Common.Utils;
using DTS.Common.XMLUtils;
using Prism.Events;
using Prism.Ioc;
// ReSharper disable UnusedVariable
// ReSharper disable UnusedMember.Local
// ReSharper disable SuggestBaseTypeForParameter
// ReSharper disable RedundantAssignment
// ReSharper disable CheckNamespace
namespace DTS.Common.Classes.Viewer.TestMetadata
{
public class TestMetadataList
{
#pragma warning disable 1998
public async Task<ObservableCollection<ITestSummary>> GetTestSummaryListAsync(IBaseViewModel parent, string path, string file, string pattern = "")
#pragma warning restore 1998
{
return GetTestSummaryList(parent, path, file, pattern);
}
public ObservableCollection<ITestSummary> GetTestSummaryList(IBaseViewModel parent, string path, string file = "", string pattern = "")
{
return new ObservableCollection<ITestSummary>(BuildITestSummary(GetTestMetadataList(TestMetadataXml.GetTestMetadataXml(path, file, string.IsNullOrEmpty(pattern) ? ".dts" : pattern), path, file), parent));
}
public ObservableCollection<ITestSummary> GetTestSummaryList(string path, string file = "", string pattern = "")
{
return new ObservableCollection<ITestSummary>(BuildITestSummary(GetTestMetadataList(TestMetadataXml.GetTestMetadataXml(path, file, string.IsNullOrEmpty(pattern) ? ".dts" : pattern), path, file)));
}
private static string ParseEventNumber(string path)
{
var segments = path.Split('\\');
return Array.Find(segments, p => p.StartsWith($"{DTS.Common.Constants.EventNumber}"));
}
private static List<ITestSummary> BuildITestSummary(IEnumerable<ITestMetadata> metadata, IBaseViewModel parent)
{
List<ITestSummary> ts;
try
{
ts = metadata.Select(md => new TestSummary
{
TestMetadata = md,
SetupName = md.TestSetup.SetupName,
Id = md.TestRun.Id + ParseEventNumber(md.TestRun.FilePath),
Description = md.TestRun.Description,
FileDate = md.TestRun.FileDate,
TimeStamp = GetTimestamp(md),
ChannelCount = md.TestRun.Channels.Count,
DataType = md.TestRun.DataType,
IsSelected = false,
Parent = parent,
Graphs = md.TestSetup.TestGraphs,
Channels = md.TestRun.Channels,
CalculatedChannels = md.TestRun.CalculatedChannels,
CalibrationBehavior = md.TestSetup.CalibrationBehavior
}).Cast<ITestSummary>().OrderByDescending(x => x.TimeStamp.Ticks).ToList();
}
catch (Exception ex)
{
var error = ex.Message;
ts = new List<ITestSummary>();
}
return ts;
}
//FB 29410 Get DateTime with milli seconds if the date is before 1/1/1990 then use the TimeStamp from testsetup
private static DateTime GetTimestamp(ITestMetadata md)
{
var basemodules = md.TestRun.Modules.GroupBy(module => module.BaseSerialNumber).Select(group => group.First());
List<TestModuleTimeStamp> testModuleTimeStamps = new List<TestModuleTimeStamp>();
foreach (var module in basemodules)
{
TestModuleTimeStamp testModuleTimeStamp =
new TestModuleTimeStamp { TriggerTimestampSec = module.TriggerTimestampSec, TriggerTimestampNanoSec = module.TriggerTimestampNanoSec };
if ( testModuleTimeStamp.TriggerTimestampSec == 0 && testModuleTimeStamp.TriggerTimestampNanoSec == 0)
{
testModuleTimeStamp = new TestModuleTimeStamp() { TriggerTimestampSec = module.StartRecordTimestampSec, TriggerTimestampNanoSec = module.StartRecordTimestampNanoSec };
}
testModuleTimeStamps.Add(testModuleTimeStamp);
}
var tuplesTime = TestUtils.MinUnixTime(testModuleTimeStamps);
if (null != tuplesTime && PTP1588Timestamps.IsValidTimeStamp(tuplesTime.Item1))
{
var time = PTP1588Timestamps.UnixTimeStampToDateTimeLocal(tuplesTime.Item1);
double ticks = tuplesTime.Item2 / 100.00;
var timeWithTicks = time.AddTicks((long)ticks);
return timeWithTicks;
}
return md.TestSetup.TimeStamp;
}
private static List<ITestSummary> BuildITestSummary(IEnumerable<ITestMetadata> metadata)
{
List<ITestSummary> ts;
try
{
ts = metadata.Select(md => new TestSummary
{
TestMetadata = md,
SetupName = md.TestSetup.SetupName,
Id = md.TestRun.Id + ParseEventNumber(md.TestRun.FilePath),
Description = md.TestRun.Description,
FileDate = md.TestRun.FileDate,
TimeStamp = GetTimestamp(md),
ChannelCount = md.TestRun.Channels.Count,
DataType = md.TestRun.DataType,
IsSelected = false,
//Parent = parent,
Graphs = md.TestSetup.TestGraphs,
Channels = md.TestRun.Channels,
CalculatedChannels = md.TestRun.CalculatedChannels,
CalibrationBehavior = md.TestSetup.CalibrationBehavior
}).Cast<ITestSummary>().OrderByDescending(x => x.TimeStamp.Ticks).ToList();
}
catch (Exception ex)
{
var error = ex.Message;
ts = new List<ITestSummary>();
}
return ts;
}
private const string TEST_NAME = "TSRAIR_GO_TEST";
/// <summary>
/// Return list of files
/// </summary>
/// <param name="xDoc">.dts file in xml format</param>
/// <param name="path">.dts file path</param>
/// <param name="file">.dts file name</param>
/// <returns></returns>
public List<ITestMetadata> GetTestMetadataList(XDocument xDoc, string path, string file)
{
List<ITestMetadata> tm;
//keep track of any tests that fail to load and warn of them
List<ITestMetadata> tmToRemove = new List<ITestMetadata>();
try
{
var items = xDoc.Elements("Tests").Elements("TestMetadata")
.Select(x => new TestMetadata
{
TestRun = GetTestRunMetadata(x),
TestSetup = GetTestSetupMetadata(x)
}).Cast<ITestMetadata>();
if (RunTestVariables.IsTSRAIRGo)
{
tm = items.Where(x => x.TestRun.FilePath.Contains(TEST_NAME)).ToList();
}
else { tm = items.ToList(); }
var errors = new List<string>();
foreach (var testMetadata in tm)
{
try
{
testMetadata.TestRun.Channels =
new ITestChannel[testMetadata.TestRun.Modules.Select(x => x.NumberOfChannels).ToList()
.Sum()].ToList();
}
catch (Exception ex)
{
errors.Add($"Failed to load channels from {testMetadata.TestSetup.SetupName} - {ex.Message}");
tmToRemove.Add(testMetadata);
}
}
if (errors.Any())
{
var eventAggregator = ContainerLocator.Container.Resolve<IEventAggregator>();
eventAggregator.GetEvent<Events.PageErrorEvent>()
.Publish(new Events.PageErrorArg(errors.ToArray(), null));
}
foreach (var metaData in tmToRemove)
{
tm.Remove(metaData);
}
}
catch (Exception ex)
{
var error = ex.Message;
tm = new List<ITestMetadata>();
}
return tm;
}
#region TestMetadata
private static DateTime GetDateTime(string dataString)
{
if (string.Equals("NOVALUE", dataString)) return DateTime.MinValue;
return Convert.ToDateTime(dataString, CultureInfo.InvariantCulture);
}
#region TestSetupMetadata
/// <summary>
/// Returns Test setup metadata
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
private TestSetupMetadata GetTestSetupMetadata(XElement x)
{
TestSetupMetadata ts;
try
{
if (x.Element("TestSetup") != null)
{
ts = (from c in x.Descendants("TestSetup")
select new TestSetupMetadata
{
SetupName = c.Element(TestSetupMetadataFields.Name.ToString())?.Value,
TimeStamp = GetDateTime(c.Element(TestSetupMetadataFields.Timestamp.ToString())?.Value),
TestGraphs = GetTestSetupGraphs(c.Element(TestSetupMetadataFields.Graphs.ToString())),
CalibrationBehavior = (CalibrationBehaviors)Enum.Parse(typeof(CalibrationBehaviors), c.Element(TestSetupMetadataFields.CalibrationBehavior.ToString())?.Value ?? CalibrationBehaviors.NonLinearIfAvailable.ToString())
}).FirstOrDefault();
}
else
{
ts = new TestSetupMetadata
{
SetupName = "N/A",
TimeStamp = DateTime.MinValue,
TestGraphs = new List<ITestGraphs>(),
CalibrationBehavior = CalibrationBehaviors.NonLinearIfAvailable
};
}
}
catch (Exception ex)
{
var error = ex.Message;
ts = new TestSetupMetadata();
}
return ts;
}
/// <summary>
/// Returns graphs
/// </summary>
/// <param name="xTestGraphs"></param>
/// <returns></returns>
private List<ITestGraphs> GetTestSetupGraphs(XElement xTestGraphs)
{
List<ITestGraphs> tg;
try
{
tg = (from c in xTestGraphs.Descendants("Graph")
select new TestGraphs
{
Name = c.Element(TestGraphsFields.Name.ToString())?.Value,
HardwareChannelName = c.Element(TestGraphsFields.HardwareChannelName.ToString())?.Value,
ChannelIds = GetChannelIds(c.Element(TestGraphsFields.Channels.ToString()))
}).Cast<ITestGraphs>().ToList();
}
catch (Exception ex)
{
var error = ex.Message;
tg = new List<ITestGraphs>();
}
return tg;
}
/// <summary>
/// Returns graph's list of ChannelIds
/// </summary>
/// <param name="xChannelIds"></param>
/// <returns></returns>
private List<string> GetChannelIds(XElement xChannelIds)
{
try
{
return (from c in xChannelIds.Descendants(TestGraphsFields.Channel.ToString()) select c.Element(TestGraphsFields.ChannelId.ToString())?.Value).ToList();
}
catch (Exception ex)
{
var error = ex.Message;
return new List<string>();
}
}
#endregion TestSetupMetadata
#region TestRunMetadata
/// <summary>
/// returns TestRun Metadata
/// </summary>
/// <param name="x">DataPRO data folder</param>
/// <returns></returns>
private TestRunMetadata GetTestRunMetadata(XElement x)
{
TestRunMetadata td;
try
{
td = (from c in x.Descendants("Test")
select new TestRunMetadata
{
/* Name is id in DTS file, id is a file name */
Id = Path.GetFileNameWithoutExtension(c.Attribute(TestRunMetadataFields.FilePath.ToString())?.Value),
Name = c.Attribute(TestRunMetadataFields.Id.ToString())?.Value,
Description = c.Attribute(TestRunMetadataFields.Description.ToString())?.Value,
InlineSerializedData = ParseBoolean(c.Attribute(TestRunMetadataFields.InlineSerializedData.ToString())?.Value),
TestGuid = c.Attribute(TestRunMetadataFields.Guid.ToString())?.Value,
FaultFlags = ParseInt(c.Attribute(TestRunMetadataFields.FaultFlags.ToString())?.Value),
Software = c.Attribute(TestRunMetadataFields.Software.ToString())?.Value,
SoftwareVersion = c.Attribute(TestRunMetadataFields.SoftwareVersion.ToString())?.Value,
DataType = c.Attribute(TestRunMetadataFields.DataType.ToString())?.Value,
FilePath = c.Attribute(TestRunMetadataFields.FilePath.ToString())?.Value,
FileDate = ParseDateTime(c.Attribute(TestRunMetadataFields.FileDate.ToString())?.Value),
Modules = LoadTestModules(c.Element(TestRunMetadataFields.Modules.ToString()), c.Attribute(TestRunMetadataFields.Id.ToString())?.Value, Path.GetFileNameWithoutExtension(c.Attribute(TestRunMetadataFields.FilePath.ToString())?.Value)),
//Channels = LoadTestChannels(c.Elements(TestRunMetadataFields.Modules.ToString()).Elements(TestRunMetadataFields.Module.ToString()).Elements(TestRunMetadataFields.Channels.ToString())),
//CalculatedChannels = LoadTestCalculatedChannel(c.Elements(TestRunMetadataFields.Modules.ToString()).Elements(TestRunMetadataFields.Module.ToString()).Elements(TestRunMetadataFields.CalculatedChannels.ToString())),
}).FirstOrDefault();
}
catch (Exception ex)
{
var error = ex.Message;
td = new TestRunMetadata();
}
return td;
}
/// <summary>
/// Returns list of all Test Modules
/// </summary>
/// <param name="xTestModules">Modules xml node</param>
/// <param name="testSetupName"></param>
/// <param name="testId"></param>
/// <returns></returns>
private List<ITestModule> LoadTestModules(XElement xTestModules, string testSetupName, string testId)
{
List<ITestModule> tm;
try
{
tm = (from m in xTestModules.Descendants("Module")
select new TestModule
{
SerialNumber = m.Attribute(TestModuleFields.SerialNumber.ToString())?.Value,
BaseSerialNumber = m.Attribute(TestModuleFields.BaseSerialNumber.ToString())?.Value,
AaFilterRateHz = ParseInt(m.Attribute(TestModuleFields.AaFilterRateHz.ToString())?.Value),
Number = ParseInt(m.Attribute(TestModuleFields.Number.ToString())?.Value),
NumberOfSamples = ParseInt(m.Attribute(TestModuleFields.NumberOfSamples.ToString())?.Value),
UnsubsampledNumberOfSamples = ParseInt(m.Attribute(TestModuleFields.UnsubsampledNumberOfSamples.ToString())?.Value),
RequestedPostTriggerSeconds = ParseDouble(m.Attribute(TestModuleFields.RequestedPostTriggerSeconds.ToString())?.Value),
RequestedPreTriggerSeconds = ParseDouble(m.Attribute(TestModuleFields.RequestedPreTriggerSeconds.ToString())?.Value),
PostTriggerSeconds = ParseDouble(m.Attribute(TestModuleFields.PostTriggerSeconds.ToString())?.Value),
PreTriggerSeconds = ParseDouble(m.Attribute(TestModuleFields.PreTriggerSeconds.ToString())?.Value),
RecordingMode = m.Attribute(TestModuleFields.RecordingMode.ToString())?.Value,
SampleRateHz = ParseInt(m.Attribute(TestModuleFields.SampleRateHz.ToString())?.Value),
StartRecordSampleNumber = ParseInt(m.Attribute(TestModuleFields.StartRecordSampleNumber.ToString())?.Value),
NumberOfChannels = ParseInt(m.Attribute(TestModuleFields.NumberOfChannels.ToString())?.Value),
InlineSerializedData = ParseBoolean(m.Attribute(TestModuleFields.InlineSerializedData.ToString())?.Value),
StartRecordTimestampSec = ParseInt(m.Attribute(TestModuleFields.StartRecordTimestampSec.ToString())?.Value),
StartRecordTimestampNanoSec = ParseInt(m.Attribute(TestModuleFields.StartRecordTimestampNanoSec.ToString())?.Value),
TriggerTimestampSec = ParseInt(m.Attribute(TestModuleFields.TriggerTimestampSec.ToString())?.Value),
TriggerTimestampNanoSec = ParseInt(m.Attribute(TestModuleFields.TriggerTimestampNanoSec.ToString())?.Value),
TriggerSampleNumbers = LoadTriggerSampleNumbers(m.Elements("TriggerSampleNumbers")),
PTPMasterSync = ParseBoolean(m.Attribute(TestModuleFields.PTPMasterSync.ToString())?.Value),
TiltSensorAxisXDegreesPre = ParseInt(m.Attribute(TestModuleFields.TiltSensorAxisXDegreesPre.ToString())?.Value),
TiltSensorAxisYDegreesPre = ParseInt(m.Attribute(TestModuleFields.TiltSensorAxisYDegreesPre.ToString())?.Value),
TiltSensorAxisZDegreesPre = ParseInt(m.Attribute(TestModuleFields.TiltSensorAxisZDegreesPre.ToString())?.Value),
TiltSensorAxisXDegreesPost = ParseInt(m.Attribute(TestModuleFields.TiltSensorAxisXDegreesPost.ToString())?.Value),
TiltSensorAxisYDegreesPost = ParseInt(m.Attribute(TestModuleFields.TiltSensorAxisYDegreesPost.ToString())?.Value),
TiltSensorAxisZDegreesPost = ParseInt(m.Attribute(TestModuleFields.TiltSensorAxisZDegreesPost.ToString())?.Value),
TemperatureLocation1Pre = ParseInt(m.Attribute(TestModuleFields.TemperatureLocation1Pre.ToString())?.Value),
TemperatureLocation2Pre = ParseInt(m.Attribute(TestModuleFields.TemperatureLocation2Pre.ToString())?.Value),
TemperatureLocation3Pre = ParseInt(m.Attribute(TestModuleFields.TemperatureLocation3Pre.ToString())?.Value),
TemperatureLocation4Pre = ParseInt(m.Attribute(TestModuleFields.TemperatureLocation4Pre.ToString())?.Value),
TemperatureLocation1Post = ParseInt(m.Attribute(TestModuleFields.TemperatureLocation1Post.ToString())?.Value),
TemperatureLocation2Post = ParseInt(m.Attribute(TestModuleFields.TemperatureLocation2Post.ToString())?.Value),
TemperatureLocation3Post = ParseInt(m.Attribute(TestModuleFields.TemperatureLocation3Post.ToString())?.Value),
TemperatureLocation4Post = ParseInt(m.Attribute(TestModuleFields.TemperatureLocation4Post.ToString())?.Value),
Channels = LoadTestChannels(m.Elements("Channels"), m.Attribute(TestModuleFields.SerialNumber.ToString())?.Value, testSetupName, testId),
CalculatedChannels = LoadTestCalculatedChannels(m.Elements("CalculatedChannels"), testSetupName, testId)
}).Cast<ITestModule>().ToList();
}
catch (Exception ex)
{
var error = ex.Message;
tm = new List<ITestModule>();
}
return tm;
}
/// <summary>
/// ?
/// </summary>
/// <param name="xTriggerSampleNumbers"></param>
/// <returns></returns>
// ReSharper disable once UnusedParameter.Local
private List<ulong> LoadTriggerSampleNumbers(IEnumerable<XElement> xTriggerSampleNumbers)
{
return new List<ulong>();
}
/// <summary>
/// Returns list (IEnumerable) of all test channels
/// </summary>
/// <param name="xTestChannels">Channels xml node</param>
/// <param name="moduleId"></param>
/// <param name="testSetupName"></param>
/// <param name="testId"></param>
/// <returns></returns>
private List<ITestChannel> LoadTestChannels(IEnumerable<XElement> xTestChannels, string moduleId, string testSetupName, string testId)
{
List<ITestChannel> tc;
try
{
tc = (from m in xTestChannels.Descendants("AnalogInputChanel")
select new TestChannel
{
TestId = testId,
TestSetupName = testSetupName,
ModuleSerialNumber = moduleId,
SerialNumber = m.Attribute(TestChannelFields.SerialNumber.ToString())?.Value,
ChannelId = m.Attribute(TestChannelFields.ChannelId.ToString()) == null || ParseInt(m.Attribute(TestChannelFields.ChannelId.ToString())?.Value) == -1 ? m.GetHashCode().ToString() : m.Attribute(TestChannelFields.ChannelId.ToString())?.Value,
Description = m.Attribute(TestChannelFields.Description.ToString())?.Value,
ChannelType = m.Attribute(TestChannelFields.ChannelType.ToString())?.Value,
Number = ParseInt(m.Attribute(TestChannelFields.Number.ToString())?.Value),
DigitalMultiplier = m.Attribute(TestChannelFields.DigitalMultiplier.ToString())?.Value,
DigitalMode = m.Attribute(TestChannelFields.DigitalMode.ToString())?.Value,
Start = GetDateTime(m.Attribute(TestChannelFields.Start.ToString())?.Value),
Bridge = m.Attribute(TestChannelFields.Bridge.ToString())?.Value,
BridgeResistanceOhms = ParseDouble(m.Attribute(TestChannelFields.BridgeResistanceOhms.ToString())?.Value),
ZeroPoint = ParseDouble(m.Attribute(TestChannelFields.ZeroPoint.ToString())?.Value),
ChannelDescriptionString = m.Attribute(TestChannelFields.ChannelDescriptionString.ToString())?.Value,
ChannelName2 = m.Attribute(TestChannelFields.ChannelName2.ToString())?.Value,
HardwareChannelName = m.Attribute(TestChannelFields.HardwareChannelName.ToString())?.Value,
DesiredRange = ParseDouble(m.Attribute(TestChannelFields.DesiredRange.ToString())?.Value),
Sensitivity = ParseDouble(m.Attribute(TestChannelFields.Sensitivity.ToString())?.Value),
SoftwareFilter = m.Attribute(TestChannelFields.SoftwareFilter.ToString())?.Value,
ProportionalToExcitation = ParseBoolean(m.Attribute(TestChannelFields.ProportionalToExcitation.ToString())?.Value),
IsInverted = ParseBoolean(m.Attribute(TestChannelFields.IsInverted.ToString())?.Value),
LinearizationFormula = m.Attribute(TestChannelFields.LinearizationFormula.ToString())?.Value,
IsSubsampled = ParseBoolean(m.Attribute(TestChannelFields.IsSubsampled.ToString())?.Value),
AbsoluteDisplayOrder = ParseInt(m.Attribute(TestChannelFields.AbsoluteDisplayOrder.ToString())?.Value),
LastCalibrationDate = GetDateTime(m.Attribute(TestChannelFields.LastCalibrationDate.ToString())?.Value),
SensorId = m.Attribute(TestChannelFields.SensorId.ToString())?.Value,
OffsetToleranceLowMv = ParseInt(m.Attribute(TestChannelFields.OffsetToleranceLowMv.ToString())?.Value),
OffsetToleranceHighMv = ParseInt(m.Attribute(TestChannelFields.OffsetToleranceHighMv.ToString())?.Value),
DataFlag = ParseInt(m.Attribute(TestChannelFields.DataFlag.ToString())?.Value),
ExcitationVoltage = m.Attribute(TestChannelFields.ExcitationVoltage.ToString())?.Value,
Eu = m.Attribute(TestChannelFields.Eu.ToString())?.Value,
CalSignalEnabled = ParseBoolean(m.Attribute(TestChannelFields.CalSignalEnabled.ToString())?.Value),
ShuntEnabled = ParseBoolean(m.Attribute(TestChannelFields.ShuntEnabled.ToString())?.Value),
VoltageInsertionCheckEnabled = ParseBoolean(m.Attribute(TestChannelFields.VoltageInsertionCheckEnabled.ToString())?.Value),
RemoveOffset = ParseBoolean(m.Attribute(TestChannelFields.RemoveOffset.ToString())?.Value),
ZeroMethod = m.Attribute(TestChannelFields.ZeroMethod.ToString())?.Value,
ZeroAverageWindowBegin = ParseDouble(m.Attribute(TestChannelFields.ZeroAverageWindowBegin.ToString())?.Value),
ZeroAverageWindowEnd = ParseDouble(m.Attribute(TestChannelFields.ZeroAverageWindowEnd.ToString())?.Value),
InitialEu = ParseInt(m.Attribute(TestChannelFields.InitialEu.ToString())?.Value),
InitialOffset = m.Attribute(TestChannelFields.InitialOffset.ToString())?.Value,
UnsubsampledSampleRateHz = ParseInt(m.Attribute(TestChannelFields.UnsubsampledSampleRateHz.ToString())?.Value),
MeasuredShuntDeflectionMv = ParseDouble(m.Attribute(TestChannelFields.MeasuredShuntDeflectionMv.ToString())?.Value),
TargetShuntDeflectionMv = ParseDouble(m.Attribute(TestChannelFields.TargetShuntDeflectionMv.ToString())?.Value),
MeasuredExcitationVoltage = ParseDouble(m.Attribute(TestChannelFields.MeasuredExcitationVoltage.ToString())?.Value),
FactoryExcitationVoltage = ParseDouble(m.Attribute(TestChannelFields.FactoryExcitationVoltage.ToString())?.Value),
TimeOfFirstSample = ParseDouble(m.Attribute(TestChannelFields.TimeOfFirstSample.ToString())?.Value),
Multiplier = m.Attribute(TestChannelFields.Multiplier.ToString()) == null ? 1 : ParseDouble(m.Attribute(TestChannelFields.Multiplier.ToString())?.Value),
UserOffsetEu = ParseDouble(m.Attribute(TestChannelFields.UserOffsetEU.ToString())?.Value),
UnitConversion = m.Attribute(TestChannelFields.UnitConversion.ToString()) == null ? 1 : ParseInt(m.Attribute(TestChannelFields.UnitConversion.ToString())?.Value),
AtCapacity = ParseBoolean(m.Attribute(TestChannelFields.AtCapacity.ToString())?.Value),
CapacityOutputIsBasedOn = ParseInt(m.Attribute(TestChannelFields.CapacityOutputIsBasedOn.ToString())?.Value),
SensitivityUnits = m.Attribute(TestChannelFields.SensitivityUnits.ToString())?.Value,
SensorCapacity = ParseInt(m.Attribute(TestChannelFields.SensorCapacity.ToString())?.Value),
SensorPolarity = m.Attribute(TestChannelFields.SensorPolarity.ToString())?.Value,
IsoCode = m.Attribute(TestChannelFields.IsoCode.ToString())?.Value ?? string.Empty,
IsoChannelName = m.Attribute(TestChannelFields.IsoChannelName.ToString())?.Value ?? string.Empty,
UserCode = m.Attribute(TestChannelFields.UserCode.ToString())?.Value ?? string.Empty,
UserChannelName = m.Attribute(TestChannelFields.UserChannelName.ToString())?.Value ?? string.Empty,
UseEUScaler = ParseBoolean(m.Attribute(TestChannelFields.UseEUScaler.ToString())?.Value),
ScaleFactorEU = ParseDouble(m.Attribute(TestChannelFields.ScaleFactorEU.ToString())?.Value),
}).Cast<ITestChannel>().ToList();
}
catch (Exception ex)
{
var error = ex.Message;
tc = new List<ITestChannel>();
}
return tc;
}
/// <summary>
/// Load Calculated Channels
/// </summary>
/// <param name="xTestCalculatedChannel"></param>
/// <param name="testSetupName"></param>
/// <param name="testId"></param>
/// <returns></returns>
private List<ITestChannel> LoadTestCalculatedChannels(IEnumerable<XElement> xTestCalculatedChannel, string testSetupName, string testId)
{
List<ITestChannel> list = new List<ITestChannel>();
try
{
var calculatedChannelsPart = xTestCalculatedChannel.Descendants("CalculatedChannel");
foreach (var m in calculatedChannelsPart)
{
var tc = new TestChannel()
{
TestId = testId,
TestSetupName = testSetupName,
IsCalculatedChannel = true,
ChannelId =
m.Attribute(TestChannelFields.ChannelId.ToString()) == null ||
ParseInt(m.Attribute(TestChannelFields.ChannelId.ToString())?.Value) == -1
? m.GetHashCode().ToString()
: m.Attribute(TestChannelFields.ChannelId.ToString())?.Value,
//37943, wipe info for calculated channels that's just the first channel's info
SerialNumber = Strings.Strings.Table_NA,
Description = m.Attribute(TestChannelFields.Description.ToString())?.Value,
ChannelType = m.Attribute(TestChannelFields.ChannelType.ToString())?.Value,
Number = ParseInt(m.Attribute(TestChannelFields.Number.ToString())?.Value),
DigitalMultiplier = m.Attribute(TestChannelFields.DigitalMultiplier.ToString())?.Value,
DigitalMode = m.Attribute(TestChannelFields.DigitalMode.ToString())?.Value,
Start = GetDateTime(m.Attribute(TestChannelFields.Start.ToString())?.Value),
Bridge = m.Attribute(TestChannelFields.Bridge.ToString())?.Value,
BridgeResistanceOhms =
ParseDouble(m.Attribute(TestChannelFields.BridgeResistanceOhms.ToString())?.Value),
ChannelDescriptionString =
m.Attribute(TestChannelFields.ChannelDescriptionString.ToString())?.Value,
ChannelName2 = m.Attribute(TestChannelFields.ChannelName2.ToString())?.Value,
HardwareChannelName = Strings.Strings.Table_NA,
DesiredRange = ParseDouble(m.Attribute(TestChannelFields.DesiredRange.ToString())?.Value),
Sensitivity = ParseDouble(m.Attribute(TestChannelFields.Sensitivity.ToString())?.Value),
SoftwareFilter = m.Attribute(TestChannelFields.SoftwareFilter.ToString())?.Value,
ProportionalToExcitation =
ParseBoolean(m.Attribute(TestChannelFields.ProportionalToExcitation.ToString())?.Value),
IsInverted = ParseBoolean(m.Attribute(TestChannelFields.IsInverted.ToString())?.Value),
LinearizationFormula = m.Attribute(TestChannelFields.LinearizationFormula.ToString())?.Value,
IsSubsampled = ParseBoolean(m.Attribute(TestChannelFields.IsSubsampled.ToString())?.Value),
AbsoluteDisplayOrder =
ParseInt(m.Attribute(TestChannelFields.AbsoluteDisplayOrder.ToString())?.Value),
LastCalibrationDate =
GetDateTime(m.Attribute(TestChannelFields.LastCalibrationDate.ToString())?.Value),
SensorId = m.Attribute(TestChannelFields.SensorId.ToString())?.Value,
OffsetToleranceLowMv =
ParseInt(m.Attribute(TestChannelFields.OffsetToleranceLowMv.ToString())?.Value),
OffsetToleranceHighMv =
ParseInt(m.Attribute(TestChannelFields.OffsetToleranceHighMv.ToString())?.Value),
DataFlag = ParseInt(m.Attribute(TestChannelFields.DataFlag.ToString())?.Value),
ExcitationVoltage = m.Attribute(TestChannelFields.ExcitationVoltage.ToString())?.Value,
Eu = m.Attribute(TestChannelFields.Eu.ToString())?.Value,
CalSignalEnabled =
ParseBoolean(m.Attribute(TestChannelFields.CalSignalEnabled.ToString())?.Value),
ShuntEnabled = ParseBoolean(m.Attribute(TestChannelFields.ShuntEnabled.ToString())?.Value),
VoltageInsertionCheckEnabled =
ParseBoolean(m.Attribute(TestChannelFields.VoltageInsertionCheckEnabled.ToString())?.Value),
RemoveOffset = ParseBoolean(m.Attribute(TestChannelFields.RemoveOffset.ToString())?.Value),
ZeroMethod = m.Attribute(TestChannelFields.ZeroMethod.ToString())?.Value,
ZeroAverageWindowBegin =
ParseDouble(m.Attribute(TestChannelFields.ZeroAverageWindowBegin.ToString())?.Value),
ZeroAverageWindowEnd =
ParseDouble(m.Attribute(TestChannelFields.ZeroAverageWindowEnd.ToString())?.Value),
InitialEu = ParseInt(m.Attribute(TestChannelFields.InitialEu.ToString())?.Value),
InitialOffset = m.Attribute(TestChannelFields.InitialOffset.ToString())?.Value,
UnsubsampledSampleRateHz =
ParseInt(m.Attribute(TestChannelFields.UnsubsampledSampleRateHz.ToString())?.Value),
MeasuredShuntDeflectionMv =
ParseDouble(m.Attribute(TestChannelFields.MeasuredShuntDeflectionMv.ToString())?.Value),
MeasuredExcitationVoltage =
ParseDouble(m.Attribute(TestChannelFields.MeasuredExcitationVoltage.ToString())?.Value),
FactoryExcitationVoltage =
ParseInt(m.Attribute(TestChannelFields.UnsubsampledSampleRateHz.ToString())?.Value),
TimeOfFirstSample =
ParseDouble(m.Attribute(TestChannelFields.MeasuredShuntDeflectionMv.ToString())?.Value),
Multiplier = m.Attribute(TestChannelFields.Multiplier.ToString()) == null
? 1
: ParseDouble(m.Attribute(TestChannelFields.Multiplier.ToString())?.Value),
UserOffsetEu = ParseDouble(m.Attribute(TestChannelFields.UserOffsetEU.ToString())?.Value),
UnitConversion = m.Attribute(TestChannelFields.UnitConversion.ToString()) == null
? 1
: ParseInt(m.Attribute(TestChannelFields.UnitConversion.ToString())?.Value),
AtCapacity = ParseBoolean(m.Attribute(TestChannelFields.AtCapacity.ToString())?.Value),
CapacityOutputIsBasedOn =
ParseInt(m.Attribute(TestChannelFields.CapacityOutputIsBasedOn.ToString())?.Value),
SourceChannelNumber = m.Attribute(TestChannelFields.SourceChannelNumber.ToString())?.Value,
SourceModuleNumber = m.Attribute(TestChannelFields.SourceModuleNumber.ToString())?.Value,
SourceModuleSerialNumber =
m.Attribute(TestChannelFields.SourceModuleSerialNumber.ToString())?.Value,
Calculation = m.Attribute(TestChannelFields.Calculation.ToString())?.Value,
SampleRateHz = ParseInt(m.Attribute(TestChannelFields.SampleRateHz.ToString())?.Value),
//37943, wipe info for calculated channels that's just the first channel's info
IsoCode = Strings.Strings.Table_NA,
//37943, wipe info for calculated channels that's just the first channel's info
IsoChannelName = Strings.Strings.Table_NA,
//37943, wipe info for calculated channels that's just the first channel's info
UserCode = Strings.Strings.Table_NA,
//37943, wipe info for calculated channels that's just the first channel's info
UserChannelName = Strings.Strings.Table_NA,
UseEUScaler = ParseBoolean(m.Attribute(TestChannelFields.UseEUScaler.ToString())?.Value),
ScaleFactorEU = ParseDouble(m.Attribute(TestChannelFields.ScaleFactorEU.ToString())?.Value),
};
var hic = m.Attribute("HIC");
if (null != hic)
{
if (double.TryParse(hic.Value, out var d))
{
tc.HIC = d;
tc.T1Sample = ulong.Parse(m.Attribute("T1").Value);
tc.T2Sample = ulong.Parse(m.Attribute("T2").Value);
}
}
list.Add(tc);
}
}
catch (Exception ex)
{
var error = ex.Message;
list = new List<ITestChannel>();
}
return list;
}
#endregion TestRunMetadata
#endregion TestMetadata
#region Support functions
/// <summary>
/// Safer way to parse
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
private int ParseInt(string param)
{
var result = 0;
int.TryParse(param, out result);
return result;
}
/// <summary>
/// Safer way to parse
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
private double ParseDouble(string param)
{
double.TryParse(param, NumberStyles.Any, CultureInfo.InvariantCulture, out var result);
return result;
}
/// <summary>
/// Safer way to parse
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
private bool ParseBoolean(string param)
{
bool.TryParse(param, out var result);
return result;
}
private DateTime ParseDateTime(string param)
{
DateTime.TryParse(param, out var result);
return result;
}
#endregion Support functions
}
}

View File

@@ -0,0 +1,57 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using DTS.Common.Interface;
// ReSharper disable CheckNamespace
namespace DTS.Common.Classes.Viewer.TestMetadata
{
public class TestModule : ITestModule
{
public string SerialNumber { get; set; }
public string BaseSerialNumber { get; set; }
public int AaFilterRateHz { get; set; }
public int Number { get; set; }
public int NumberOfSamples { get; set; }
public int UnsubsampledNumberOfSamples { get; set; }
public double RequestedPostTriggerSeconds { get; set; }
public double RequestedPreTriggerSeconds { get; set; }
public double PostTriggerSeconds { get; set; }
public double PreTriggerSeconds { get; set; }
public string RecordingMode { get; set; }
public int SampleRateHz { get; set; }
public int StartRecordSampleNumber { get; set; }
public int NumberOfChannels { get; set; }
public bool InlineSerializedData { get; set; }
public int StartRecordTimestampSec { get; set; }
public int StartRecordTimestampNanoSec { get; set; }
public int TriggerTimestampSec { get; set; }
public int TriggerTimestampNanoSec { get; set; }
public List<ulong> TriggerSampleNumbers { get; set; }
public bool PTPMasterSync { get; set; }
public int TiltSensorAxisXDegreesPre { get; set; }
public int TiltSensorAxisYDegreesPre { get; set; }
public int TiltSensorAxisZDegreesPre { get; set; }
public int TiltSensorAxisXDegreesPost { get; set; }
public int TiltSensorAxisYDegreesPost { get; set; }
public int TiltSensorAxisZDegreesPost { get; set; }
public int TemperatureLocation1Pre { get; set; }
public int TemperatureLocation2Pre { get; set; }
public int TemperatureLocation3Pre { get; set; }
public int TemperatureLocation4Pre { get; set; }
public int TemperatureLocation1Post { get; set; }
public int TemperatureLocation2Post { get; set; }
public int TemperatureLocation3Post { get; set; }
public int TemperatureLocation4Post { get; set; }
public List<ITestChannel> Channels { get; set; }
public List<ITestChannel> CalculatedChannels { get; set; }
public bool IsSelected { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using DTS.Common.Interface;
// ReSharper disable CheckNamespace
namespace DTS.Common.Classes.Viewer.TestMetadata
{
public class TestRunMetadata : ITestRunMetadata
{
public string Name { get; set; }
public string Id { get; set; }
public string Description { get; set; }
public bool InlineSerializedData { get; set; }
public string TestGuid { get; set; }
public int FaultFlags { get; set; }
public string Software { get; set; }
public string SoftwareVersion { get; set; }
public string DataType { get; set; }
public DateTime FileDate { get; set; }
public string FilePath { get; set; }
public List<ITestModule> Modules { get; set; }
public List<ITestChannel> Channels { get; set; }
public List<ITestChannel> CalculatedChannels { get; set; }
public bool IsSelected { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface;
// ReSharper disable CheckNamespace
namespace DTS.Common.Classes.Viewer.TestMetadata
{
public class TestSetupMetadata : ITestSetupMetadata
{
public string SetupName { get; set; }
public DateTime TimeStamp { get; set; }
public List<ITestGraphs> TestGraphs { get; set; }
public CalibrationBehaviors CalibrationBehavior { get; set; }
}
}

View File

@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using DTS.Common.Base;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface;
using DTS.Common.Interface.TestDefinition;
using Prism.Commands;
// ReSharper disable CheckNamespace
// ReSharper disable RedundantDefaultMemberInitializer
namespace DTS.Common.Classes.Viewer.TestMetadata
{
public class TestSummary : ITestSummary
{
/// <summary>
/// the _ROI Period x folder name if present
/// 18411 Data will not export [CSV Unfiltered]
/// </summary>
public const string ROI_SUFFIX = @"_ROI Period";
public string Id { get; set; }
public string SetupName { get; set; }
public string Description { get; set; }
public int ChannelCount { get; set; }
public DateTime FileDate { get; set; }
public DateTime TimeStamp { get; set; }
public string DataType { get; set; }
private bool _isSelected = false;
public bool IsSelected { get => _isSelected; set { if (value != IsSelected) { _isSelected = value; SelectionChanged(); OnPropertyChanged("IsSelected"); } } }
public List<ITestGraphs> Graphs { get; set; }
public List<ITestChannel> Channels { get; set; }
public List<ITestChannel> CalculatedChannels { get; set; }
public IBaseViewModel Parent { get; set; }
public CalibrationBehaviors CalibrationBehavior { get; set; } = CalibrationBehaviors.NonLinearIfAvailable;
public ITestMetadata TestMetadata { get; set; }
#region Commands
private DelegateCommand _isSelectedCommand;
public DelegateCommand IsSelectedCommand
{
get => _isSelectedCommand ?? (_isSelectedCommand = new DelegateCommand(SelectionChanged));
set => _isSelectedCommand = value;
}
public void SelectionChanged()
{
var parent = (ITestSummaryListViewModel)Parent;
if (parent == null) return;
var list = parent.SelectedTestSummaryList;
if (IsSelected) { if (!list.Contains(this)) list.Add(this); }
else { if (list.Contains(this)) list.Remove(this); }
parent.PublishSelectedTestSummaryList();
}
#endregion Commands
///<summary>
///Occurs when a property value changes.
///</summary>
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,9 @@
namespace DTS.Common.Classes.GroupTemplates
{
public static class Constants
{
public const string NON_ISO_TESTOBJECT_CHANNEL_TYPE = "x_NonISOTestObjectType_x";
public const string NON_ISO_TESTOBJECT_NAME = "x_NonISOTestObjectName_x";
public const string NON_ISO_TESTOBJECT_CHANNEL_TYPE2 = "NONISO_x_";
}
}

View File

@@ -0,0 +1,157 @@
using DTS.Common.Interface.Channels;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
namespace DTS.Common.Classes.Channels
{
/// <summary>
/// represents a record of a channel in the db
/// <inheritdoc cref="IChannelDbRecord"/>
/// </summary>
public class ChannelDbRecord : Base.BasePropertyChanged, IChannelDbRecord
{
protected long _id = -1;
/// <summary>
/// The database id of the Channel
/// </summary>
[Key]
public long Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private int _groupId = -1;
public int GroupId
{
get => _groupId;
set => SetProperty(ref _groupId, value, "GroupId");
}
private string _isoCode = "";
public string IsoCode
{
get => _isoCode;
set => SetProperty(ref _isoCode, value, "IsoCode");
}
private string _isoChannelName = "";
public string IsoChannelName
{
get => _isoChannelName;
set => SetProperty(ref _isoChannelName, value, "IsoChannelName");
}
private string _userCode;
public string UserCode
{
get => _userCode;
set => SetProperty(ref _userCode, value, "UserCode");
}
private string _userChannelName = "";
public string UserChannelName
{
get => _userChannelName;
set => SetProperty(ref _userChannelName, value, "UserChannelName");
}
private int _dasId = -1;
public int DASId
{
get => _dasId;
set => SetProperty(ref _dasId, value, "DASId");
}
protected int _dasChannelIndex = -1;
public int DASChannelIndex
{
get => _dasChannelIndex;
set => SetProperty(ref _dasChannelIndex, value, "DASChannelIndex");
}
private int _groupChannelOrder = -1;
public int GroupChannelOrder
{
get => _groupChannelOrder;
set => SetProperty(ref _groupChannelOrder, value, "GroupChannelOrder");
}
private int _testSetupOrder = -1;
public int TestSetupOrder
{
get => _testSetupOrder;
set => SetProperty(ref _testSetupOrder, value, "TestSetupOrder");
}
private int _sensorId = -1;
public int SensorId
{
get => _sensorId;
set => SetProperty(ref _sensorId, value, "SensorId");
}
/// <summary>
/// IsDisabled is declared here, and redirects to Disabled so that
/// existing uses of IsDisabled do not need to be modified.
/// </summary>
public bool IsDisabled
{
get => Disabled;
set
{
Disabled = value;
OnPropertyChanged("IsDisabled");
}
}
public bool Disabled { get; set; }
private DateTime _lastModified = DateTime.Today;
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private string _lastModifiedBy = "";
public string LastModifiedBy
{
get => _lastModifiedBy;
set => SetProperty(ref _lastModifiedBy, value, "LastModifiedBy");
}
public ChannelDbRecord() { }
public ChannelDbRecord(IChannelDbRecord copy)
{
Id = copy.Id;
GroupId = copy.GroupId;
IsoCode = copy.IsoCode;
IsoChannelName = copy.IsoChannelName;
UserCode = copy.UserCode;
UserChannelName = copy.UserChannelName;
DASId = copy.DASId;
DASChannelIndex = copy.DASChannelIndex;
GroupChannelOrder = copy.GroupChannelOrder;
TestSetupOrder = copy.TestSetupOrder;
SensorId = copy.SensorId;
Disabled = copy.Disabled;
LastModified = copy.LastModified;
LastModifiedBy = copy.LastModifiedBy;
}
public ChannelDbRecord(IDataReader reader)
{
Id = Utility.GetInt(reader, "Id", -1);
GroupId = Utility.GetInt(reader, "GroupId", -1);
IsoCode = Utility.GetString(reader, "IsoCode");
IsoChannelName = Utility.GetString(reader, "IsoChannelName");
UserCode = Utility.GetString(reader, "UserCode");
UserChannelName = Utility.GetString(reader, "UserChannelName");
DASId = Utility.GetInt(reader, "DASId", -1);
DASChannelIndex = Utility.GetInt(reader, "DASChannelIndex", -1);
GroupChannelOrder = Utility.GetInt(reader, "GroupChannelOrder", -1);
TestSetupOrder = Utility.GetInt(reader, "TestSetupOrder", -1);
SensorId = Utility.GetInt(reader, "SensorId", -1);
Disabled = Utility.GetBool(reader, "Disabled");
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastModifiedBy = Utility.GetString(reader, "LastModifiedBy");
}
}
}

View File

@@ -0,0 +1,161 @@
using DTS.Common.Interface.Channels;
namespace DTS.Common.Classes.Groups.ChannelSettings
{
public class ChannelSettingBase : IChannelSetting
{
//analog parameters
public const string RANGE = "Range";
public const string CFC = "CFC";
//FB 13120 Add FilterClass
public const string FilterClass = "FilterClass";
public const string POLARITY = "Polarity";
public const string POSITION = "Position";
public const string ZEROMETHOD = "ZeroMethod";
public const string ZEROMETHODSTART = "ZeroMethodStart";
public const string ZEROMETHODEND = "ZeroMethodEnd";
public const string USERVALUE1 = "UserValue1";
public const string USERVALUE2 = "UserValue2";
public const string USERVALUE3 = "UserValue3";
public const string INITIAL_OFFSET = "InitialOffset";
/// <summary>
/// the string key for the ac coupled enabled channel setting
/// http://manuscript.dts.local/f/cases/29760/Implement-ACCoupleEnable-for-TSR-AIR
/// </summary>
public const string ACCouplingEnabled = "ACCouplingEnabled";
//depreciated parameters
//public const string LIMIT_DURATION = "LimitDuration";
//public const string DURATION = "Duration";
//public const string DELAY = "Delay";
//33415 Voltage insertion channel should be half bridge
public const string BRIDGE_TYPE = "BridgeType";
//squib parameters
public const string SQUIB_CURRENT = "SquibCurrent";
public const string SQUIB_LIMIT_DURATION = "SquibLimitDuration";
public const string SQUIB_DURATION = "SquibDuration";
public const string SQUIB_DELAY = "SquibDelay";
public const string SQMODE = "SQMode";
//digital out parameters
public const string DIGITALOUT_LIMIT_DURATION = "DigitalOutLimitDuration";
public const string DIGITALOUT_DURATION = "DigitalOutDuration";
public const string DIGITALOUT_DELAY = "DigitalOutDelay";
public const string OUTPUT_MODE = "OutputMode";
//digital in parameters
public const string DIMODE = "DIMode";
public const string DEFAULT_VALUE = "DefaultValue";
public const string ACTIVE_VALUE = "ActiveValue";
//uart parameters 18363
public const string BAUD_RATE = "UartBaudRate";
public const string DATA_BITS = "UartDataBits";
public const string STOP_BITS = "UartStopBits";
public const string PARITY = "UartParity";
public const string FLOW_CONTROL = "UartFlowControl";
public const string DATA_FORMAT = "UartDataFormat";
//streamout parameters 18363
public const string UDP_PROFILE = "StreamOutUDPProfile";
public const string UDP_ADDRESS = "StreamOutUDPAddress";
public const string UDP_TIME_CHID = "StreamOutUDPTimeChannelId";
public const string UDP_DATA_CHID = "StreamOutUDPDataChannelId";
public const string UDP_TMNS_CONFIG = "StreamOutUDPTmNSConfig";
public const string IRIG_TDP_INTERVAL_MS = "StreamOutIRIGTimeDataPacketIntervalMs";
public const string TMATS_INTERVAL_MS = "StreamOutTMATSIntervalMs";
//streamin parameters 26828
public const string UDP_ADDRESS_IN = "StreamInUDPAddress";
//CAN parameters 44881
public const string CAN_IS_FD = "CanIsFD";
public const string CAN_ARB_BASE_BITRATE = "CanArbBaseBitrate";
public const string CAN_ARB_BASE_SJW = "CanArbBaseSJW";
public const string CAN_DATA_BITRATE = "CanDataBitrate";
public const string CAN_DATA_SJW = "CanDataSJW";
public const string CAN_FILE_TYPE = "CanFileType";
public ChannelSettingBase(int settingType, string name, string defaultValue)
{
SettingTypeId = settingType;
SettingName = name;
DefaultValue = defaultValue;
}
public IChannelSetting Clone()
{
return new ChannelSettingBase(this);
}
private ChannelSettingBase(IChannelSetting setting)
{
ChannelId = setting.ChannelId;
SettingTypeId = setting.SettingTypeId;
SettingName = setting.SettingName;
DefaultValue = setting.DefaultValue;
Value = setting.Value;
}
public long ChannelId { get; set; }
public int SettingTypeId { get; protected set; }
public string SettingName { get; protected set; }
public string DefaultValue { get; protected set; }
public string Value { get; set; }
public double DoubleValue
{
get
{
if (double.TryParse(Value, System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out double d))
{
return d;
}
return DoubleDefaultValue;
}
set => Value = value.ToString(System.Globalization.CultureInfo.InvariantCulture);
}
public double DoubleDefaultValue => double.Parse(DefaultValue, System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture);
public int IntValue
{
get
{
if (int.TryParse(Value, System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, out int d))
{
return d;
}
return IntDefaultValue;
}
set => Value = value.ToString(System.Globalization.CultureInfo.InvariantCulture);
}
public int IntDefaultValue => int.Parse(DefaultValue, System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture);
public bool BoolValue
{
get
{
if (bool.TryParse(Value, out bool b))
{
return b;
}
return BoolDefaultValue;
}
set => Value = value.ToString(System.Globalization.CultureInfo.InvariantCulture);
}
public bool BoolDefaultValue
{
get
{
if (bool.TryParse(DefaultValue, out var b))
{
return b;
}
if (string.IsNullOrEmpty(DefaultValue)) { return false; }
return !DefaultValue.Equals(0);
}
}
}
}

View File

@@ -0,0 +1,36 @@
using DTS.Common.Interface.Channels;
using System.Data;
namespace DTS.Common.Classes.Groups.ChannelSettings
{
public class ChannelSettingRecord : Common.Base.BasePropertyChanged, IChannelSettingRecord
{
private int _id;
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private string _settingName;
public string SettingName
{
get => _settingName;
set => SetProperty(ref _settingName, value, "SettingName");
}
private string _defaultValue;
public string DefaultValue
{
get => _defaultValue;
set => SetProperty(ref _defaultValue, value, "DefaultValue");
}
public ChannelSettingRecord() { }
public ChannelSettingRecord(IDataReader reader)
{
Id = Utility.GetInt(reader, "Id");
SettingName = Utility.GetString(reader, "SettingName");
DefaultValue = Utility.GetString(reader, "DefaultValue");
}
}
}

View File

@@ -0,0 +1,44 @@
using DTS.Common.Base;
using DTS.Common.Interface.Channels;
using System.Data;
namespace DTS.Common.Classes.Groups.ChannelSettings
{
public class GroupChannelSettingRecord : BasePropertyChanged, IGroupChannelSettingRecord
{
private long _channelId;
public long ChannelId
{
get => _channelId;
set => SetProperty(ref _channelId, value, "ChannelId");
}
private int _settingId;
public int SettingId
{
get => _settingId;
set => SetProperty(ref _settingId, value, "SettingId");
}
private string _settingValue;
public string SettingValue
{
get => _settingValue;
set => SetProperty(ref _settingValue, value, "SettingValue");
}
public GroupChannelSettingRecord() { }
public GroupChannelSettingRecord(IDataReader reader, int storedProcedureVersionUsed)
{
if (storedProcedureVersionUsed >= Constants.BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION)
{
ChannelId = Utility.GetLong(reader, "ChannelId");
}
SettingId = Utility.GetInt(reader, "SettingId");
SettingValue = Utility.GetString(reader, "SettingValue");
}
public GroupChannelSettingRecord(long channelId, int settingId, string settingValue)
{
ChannelId = channelId;
SettingId = settingId;
SettingValue = settingValue;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
using DTS.Common.Interface.Groups;
using DTS.Common.Interface.Groups.GroupList;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
namespace DTS.Common.Classes.Groups
{
/// <summary>
/// represents a record of a channel in the db
/// <inheritdoc cref="IChannelDbRecord"/>
/// </summary>
public class GroupDbRecord : Base.BasePropertyChanged, IGroupDbRecord
{
protected int _id = -1;
/// <summary>
/// The database id of the Channel
/// </summary>
[Key]
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
public string SerialNumber { get; set; }
public string Picture { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public bool Embedded { get; set; }
public DateTime LastModified { get; set; }
public string LastModifiedBy { get; set; }
public int? StaticGroupId { get; set; }
public string ExtraProperties { get; set; }
public GroupDbRecord() { }
public GroupDbRecord(IGroupDbRecord copy)
{
Id = copy.Id;
SerialNumber = copy.SerialNumber;
Picture = copy.Picture;
DisplayName = copy.DisplayName;
Description = copy.Description;
Embedded = copy.Embedded;
LastModified = copy.LastModified;
LastModifiedBy = copy.LastModifiedBy;
StaticGroupId = copy.StaticGroupId;
ExtraProperties = copy.ExtraProperties;
}
public GroupDbRecord(IGroup copy, List<KeyValuePair<string, string>> extraProperties)
{
Id = copy.Id;
SerialNumber = copy.Name;
Picture = "";
DisplayName = copy.DisplayName;
Description = copy.Description;
Embedded = copy.Embedded;
LastModified = copy.LastModified;
LastModifiedBy = copy.LastModifiedBy;
StaticGroupId = copy.StaticGroupId;
ExtraProperties = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(extraProperties);
}
public GroupDbRecord(IDataReader reader)
{
Id = Utility.GetInt(reader, "Id", -1);
SerialNumber = Utility.GetString(reader, "SerialNumber");
Picture = Utility.GetString(reader, "Picture");
DisplayName = Utility.GetString(reader, "DisplayName");
Description = Utility.GetString(reader, "Description");
Embedded = Utility.GetBool(reader, "Embedded");
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastModifiedBy = Utility.GetString(reader, "LastModifiedBy");
StaticGroupId = Utility.GetNullableInt(reader, "StaticGroupId");
ExtraProperties = Utility.GetString(reader, "ExtraProperties");
}
}
}

View File

@@ -0,0 +1,85 @@
using DTS.Common.Base;
namespace DTS.Common.Classes.Groups
{
// ReSharper disable once InconsistentNaming
/// <summary>
/// this class encapsulates a single channel or row in a TDC GRP file
/// </summary>
public class GroupGRPImportChannel : BasePropertyChanged
{
public const uint SerialNumberField = 0;
public const uint DisplayNameField = 1;
public const uint ISOCodeField = 2;
public const uint InvertField = 3;
public const uint CapacityField = 4;
public const uint InputModeField = 5;
public const uint DefaultValueField = 6;
public const uint ActiveValueField = 7;
public const uint FireModeField = 8;
public const uint DelayField = 9;
public const uint LimitDurationField = 10;
public const uint DurationField = 11;
public const uint CurrentField = 12;
public string SensorSerialNumber { get; set; }
public string DisplayName { get; set; }
public string ISOCode { get; set; }
public bool Invert { get; set; }
public double FullScale { get; set; }
public enum InputModes
{
na, //Not applicable. Used to denote a non-Digital Input channel
TLH, //TransitionLowToHigh (DigitalInput)
THL, //TransitionHighToLow (DigitalInput)
CCNO, //ContactClosureNormallyOpen(DigitalInput)
CCNC //ContactClosureNormallyClosed(DigitalInput)
}
public const InputModes DefaultInputMode = InputModes.CCNO;
public InputModes? InputMode { get; set; } = null;
public const double DefaultDefaultValue = 0.0;
public double? DefaultValue { get; set; } = null;
public const double DefaultActiveValue = 1.0;
public double? ActiveValue { get; set; } = null;
public enum FireModes
{
na, //Not applicable. Used to denote a non-Squib channel
CD, //CapacitorDischarge (Squib)
CC //ConstantCurrent (Squib)
}
public const FireModes DefaultFireMode = FireModes.CD;
public FireModes? FireMode { get; set; } = null;
public const double DefaultDelay = 0.00;
public double? Delay { get; set; } = null;
public const bool DefaultLimitDuration = true;
public bool? LimitDuration { get; set; } = null;
public const double DefaultDuration = 10.0;
public double? Duration { get; set; } = null;
public const double DefaultCurrent = 1.5;
public double? Current { get; set; } = null;
/// <summary>
/// error for the group, or null if there are no errors
/// an error at this level means the group can't be imported
/// </summary>
public GroupGRPImportError Error { get; set; } = null;
public GroupGRPImportGroup ParentGroup { get; set; }
public string GroupName => null == ParentGroup ? "---" : ParentGroup.GroupName;
/// <summary>
/// forces refresh for anything bound to GroupName
/// </summary>
public void GroupNameInvalidate()
{
OnPropertyChanged("GroupName");
}
}
}

View File

@@ -0,0 +1,35 @@
namespace DTS.Common.Classes.Groups
{
// ReSharper disable once InconsistentNaming
/// <summary>
/// this class encapsulates and enumerates all possible errors while importing a .GRP file
/// </summary>
public class GroupGRPImportError
{
public enum Errors
{
FileEmpty,
InvalidISOCodeInput,
InvalidFullScaleInput,
InvalidSensorInput,
InvalidInvertInput,
SensorNotFound,
InvalidInputMode,
InvalidDefaultValue,
InvalidActiveValue,
InvalidFireMode,
InvalidDelay,
InvalidLimitDuration,
InvalidDuration,
InvalidCurrent
}
public Errors ErrorCode { get; set; }
public string File { get; set; }
public int Line { get; set; }
public string ExtraInfo { get; set; }
public override string ToString()
{
return ExtraInfo;
}
}
}

View File

@@ -0,0 +1,42 @@
using DTS.Common.Base;
namespace DTS.Common.Classes.Groups
{
// ReSharper disable once InconsistentNaming
/// <summary>
/// this class encapsulates a group, or basically a .grp file
/// </summary>
public class GroupGRPImportGroup : BasePropertyChanged
{
public bool Included { get; set; } = true;
public bool Overwrite { get; set; } = true;
public string GroupName { get; set; }
public string GroupTags { get; set; }
public string ImportingUserTags { get; set; }
public string SourceFile { get; set; }
/// <summary>
/// all channels in the gGRP file
/// </summary>
public GroupGRPImportChannel[] Channels { get; set; } = { };
/// <summary>
/// all errors discovered while GRP file
/// this would include things like an empty file, a file with garbage only
/// </summary>
public GroupGRPImportError[] GroupErrors { get; set; } = null;
private bool _groupNameHasError;
/// <summary>
/// indicates whether the group name specifically has an error
/// the group name is exposed in a textbox, the design of this field was to
/// control a red box around that textbox
/// </summary>
public bool GroupNameHasError
{
get => _groupNameHasError;
set => SetProperty(ref _groupNameHasError, value, "GroupNameHasError");
}
}
}

View File

@@ -0,0 +1,64 @@
using DTS.Common.Interface.Groups;
using DTS.Common.Interface.Groups.GroupList;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
namespace DTS.Common.Classes.Groups
{
/// <summary>
/// represents a record in the GroupHardware table in the db
/// <inheritdoc cref="IChannelDbRecord"/>
/// </summary>
public class GroupHardwareDbRecord : Base.BasePropertyChanged, IGroupHardwareDbRecord
{
protected int _id = -1;
/// <summary>
/// The database id of the Channel
/// </summary>
[Key]
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private int _groupId = -1;
public int GroupId
{
get => _groupId;
set => SetProperty(ref _groupId, value, "GroupId");
}
private int _dasId = -1;
public int DASId
{
get => _dasId;
set => SetProperty(ref _dasId, value, "DASId");
}
private string _serialNumber = string.Empty;
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
public GroupHardwareDbRecord() { }
public GroupHardwareDbRecord(IGroupHardwareDbRecord copy)
{
Id = copy.Id;
GroupId = copy.GroupId;
DASId = copy.DASId;
SerialNumber = copy.SerialNumber;
}
public GroupHardwareDbRecord(IDataReader reader)
{
Id = Utility.GetInt(reader, "RecordId", -1);
GroupId = Utility.GetInt(reader, "GroupId", -1);
DASId = Utility.GetInt(reader, "DASId", -1);
SerialNumber = Utility.GetString(reader, "SerialNumber");
}
}
}

View File

@@ -0,0 +1,236 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DTS.Common.Classes.Groups
{
public abstract class GroupHelper
{
#region StaticGroupNames
private static Dictionary<int, string> StaticGroupNames = new Dictionary<int, string>();
public static void ClearStaticGroupNames()
{
StaticGroupNames.Clear();
}
public static void SetStaticGroupName(int id, string name)
{
StaticGroupNames[id] = name;
}
public static string GetStaticGroupName(int Id)
{
var name = string.Empty;
if (StaticGroupNames.ContainsKey(Id))
{
name = StaticGroupNames[Id];
}
return name;
}
#endregion StaticGroupNames
#region EmbeddedGroupIdList
private static List<int> EmbeddedGroupIdList = new List<int>();
public static void ClearEmbeddedGroupIdList()
{
EmbeddedGroupIdList.Clear();
}
public static void SetEmbeddedGroupId(int id)
{
EmbeddedGroupIdList.Add(id);
}
public static bool IsGroupEmbedded(int Id)
{
return EmbeddedGroupIdList.Contains(Id);
}
#endregion EmbeddedGroupIdList
#region TestSetupGroupIds
private static Dictionary<int, int> TestSetupGroupIds = new Dictionary<int, int>();
public static void ClearTestSetupGroupIds()
{
TestSetupGroupIds.Clear();
}
public static void SetTestSetupGroupId(int groupId, int testSetupId)
{
TestSetupGroupIds[groupId] = testSetupId;
}
public static int GetTestSetupGroupId(int groupId)
{
var testSetupGroupId = 0;
if (TestSetupGroupIds.ContainsKey(groupId))
{
testSetupGroupId = TestSetupGroupIds[groupId];
}
return testSetupGroupId;
}
#endregion TestSetupGroupIds
#region GroupChannelIds
private static Dictionary<int, List<int>> GroupChannelIds = new Dictionary<int, List<int>>();
public static void ClearGroupChannelIds()
{
GroupChannelIds.Clear();
}
public static void AddGroupChannelId(int sensorId, int groupId)
{
if (!GroupChannelIds.ContainsKey(sensorId))
{
GroupChannelIds.Add(sensorId, new List<int>());
}
GroupChannelIds[sensorId].Add(groupId);
}
public static List<int> GetGroupIdsFromChannels(int sensorId)
{
var groupIdList = new List<int>();
if (GroupChannelIds.ContainsKey(sensorId))
{
groupIdList = GroupChannelIds[sensorId];
}
return groupIdList;
}
#endregion
#region DASIds
private static Dictionary<string, int> DASIds = new Dictionary<string, int>();
public static void ClearDASIds()
{
DASIds.Clear();
}
public static void SetDASId(string serialNumber, int dasId)
{
DASIds[serialNumber] = dasId;
}
public static int GetDASId(string serialNumber)
{
return DASIds[serialNumber];
}
#endregion DASIds
#region BaseModuleChannelIndexList
public static Dictionary<string, Dictionary<string, List<int>>> BaseModuleChannelIndexList = new Dictionary<string, Dictionary<string, List<int>>>();
public static void ClearBaseModuleChannelIndexList()
{
BaseModuleChannelIndexList.Clear();
}
public static void SetBaseModuleChannelIndexList(string baseSerialNumberSubstring, Dictionary<string, List<int>> tempDictionary)
{
BaseModuleChannelIndexList[baseSerialNumberSubstring] = tempDictionary;
}
public static List<int> GetChannelIndexes(string targetBaseSerialNumber, string targetModuleSerialNumber)
{
var channelIndexList = new List<int>();
foreach (var baseModuleIndexListTriple in BaseModuleChannelIndexList)
{
if (baseModuleIndexListTriple.Key == targetBaseSerialNumber)
{
var moduleIndexListTuple = baseModuleIndexListTriple.Value;
foreach (var moduleSerialNumber in moduleIndexListTuple.Keys)
{
if (moduleSerialNumber == targetModuleSerialNumber)
{
channelIndexList = moduleIndexListTuple[moduleSerialNumber];
}
}
}
}
return channelIndexList;
}
#endregion BaseModuleChannelIndexList
#region DASIdChannelIndexGroupIdList
public static Dictionary<int, Dictionary<int, int>> DASIdChannelIndexGroupIdList = new Dictionary<int, Dictionary<int, int>>();
public static void ClearDASIdChannelIndexGroupIdList()
{
DASIdChannelIndexGroupIdList.Clear();
}
public static void SetDASIdChannelIndexGroupIdList(int dasId, Dictionary<int, int> tempDictionary)
{
DASIdChannelIndexGroupIdList[dasId] = tempDictionary;
}
public static List<int> GetGroupIds(int targetDasId, List<int> targetChannelIndexList)
{
var groupIdList = new List<int>();
foreach (var dasIdChannelIndexGroupIdTriple in DASIdChannelIndexGroupIdList)
{
if (dasIdChannelIndexGroupIdTriple.Key == targetDasId)
{
var channelIndexGroupIdTuple = dasIdChannelIndexGroupIdTriple.Value;
foreach (var channelIndex in channelIndexGroupIdTuple.Keys)
{
if (targetChannelIndexList.Contains(channelIndex))
{
groupIdList.Add(channelIndexGroupIdTuple[channelIndex]);
}
}
}
}
return groupIdList;
}
#endregion BaseModuleChannelIndexList
#region TestSetupHardwareIds
private static Dictionary<int, List<int>> TestSetupHardwareIds = new Dictionary<int, List<int>>();
public static void ClearTestSetupHardwareIds()
{
TestSetupHardwareIds.Clear();
}
public static void AddTestSetupHardwareId(int dasId, int testSetupId)
{
if (!TestSetupHardwareIds.ContainsKey(dasId))
{
TestSetupHardwareIds.Add(dasId, new List<int>());
}
TestSetupHardwareIds[dasId].Add(testSetupId);
}
public static List<int> GetTestSetupHardwareIds(int DASId)
{
var testSetupIdList = new List<int>();
if (TestSetupHardwareIds.ContainsKey(DASId))
{
testSetupIdList = TestSetupHardwareIds[DASId];
}
return testSetupIdList;
}
#endregion TestSetupHardwareIds
#region GroupHardwareIds
private static Dictionary<int, List<int>> GroupHardwareIds = new Dictionary<int, List<int>>();
public static void ClearGroupHardwareIds()
{
GroupHardwareIds.Clear();
}
public static void AddGroupHardwareId(int dasId, int groupId)
{
if (!GroupHardwareIds.ContainsKey(dasId))
{
GroupHardwareIds.Add(dasId, new List<int>());
}
GroupHardwareIds[dasId].Add(groupId);
}
public static List<int> GetGroupHardwareIds(int DASId)
{
var groupIdList = new List<int>();
if (GroupHardwareIds.ContainsKey(DASId))
{
groupIdList = GroupHardwareIds[DASId];
}
return groupIdList;
}
#endregion GroupHardwareIds
}
}

View File

@@ -0,0 +1,86 @@
using DTS.Common.Interface.Groups;
using System.Data;
namespace DTS.Common.Classes.Groups
{
/// <summary>
/// represents an association of groups to test setups and additional
/// test setup specific meta data for a group
/// <inheritdoc cref="ITestSetupGroupRecord"/>
/// </summary>
public class TestSetupGroupRecord : Base.BasePropertyChanged, ITestSetupGroupRecord
{
private int _groupId = -1;
/// <summary>
/// database id of group
/// </summary>
public int GroupId
{
get => _groupId;
set => SetProperty(ref _groupId, value, "GroupId");
}
private int _displayOrder = -1;
/// <summary>
/// display order of group
/// </summary>
public int DisplayOrder
{
get => _displayOrder;
set => SetProperty(ref _displayOrder, value, "DisplayOrder");
}
private string _position = "";
/// <summary>
/// Position field (ISO 13499) for group, if available
/// [groups can be made of mixed position fields]
/// </summary>
public string Position
{
get => _position;
set => SetProperty(ref _position, value, "Position");
}
private string _testObjectType = "";
/// <summary>
/// Test Object field (ISO 13499) for group, if available
/// [groups can be made of mixed test object fields]
/// </summary>
public string TestObjectType
{
get => _testObjectType;
set => SetProperty(ref _testObjectType, value, "TestObjectType");
}
private int _testSetupId = -1;
/// <summary>
/// database id of test setup group belongs to
/// </summary>
public int TestSetupId
{
get => _testSetupId;
set => SetProperty(ref _testSetupId, value, "TestSetupId");
}
public TestSetupGroupRecord() { }
/// <summary>
/// creates record using data reader
/// </summary>
/// <param name="reader"></param>
public TestSetupGroupRecord(IDataReader reader)
{
GroupId = Utility.GetInt(reader, "GroupId");
DisplayOrder = Utility.GetInt(reader, "DisplayOrder");
Position = Utility.GetString(reader, "Position");
TestObjectType = Utility.GetString(reader, "TestObjectType");
TestSetupId = Utility.GetInt(reader, "TestSetupId");
}
/// <summary>
/// copy constructor
/// </summary>
/// <param name="copy"></param>
public TestSetupGroupRecord(ITestSetupGroupRecord copy)
{
GroupId = copy.GroupId;
DisplayOrder = copy.DisplayOrder;
Position = copy.Position;
TestObjectType = copy.TestObjectType;
TestSetupId = copy.TestSetupId;
}
}
}

View File

@@ -0,0 +1,218 @@
using DTS.Common.Interface.DataRecorders;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
namespace DTS.Common.Classes.Hardware
{
/// <summary>
/// representation of a DASChannel in the db
/// <inheritdoc cref="IDASChannelDBRecord"/>
/// </summary>
public class DASChannelDBRecord : Common.Base.BasePropertyChanged, IDASChannelDBRecord
{
/// <summary>
/// a string id for the hardware the channel belongs to
/// (serialnumber_dastype)
/// </summary>
public string HardwareId { get; set; }
[Key]
[Column("DASChannelId")]
/// <summary>
/// the id/key of the DAS channel record in the db
/// </summary>
public int DaschannelId { get; set; }
[Column("DASId")]
/// <summary>
/// the das db id of the Hardware this channel belongs to
/// </summary>
public int? Dasid { get; set; }
private int _channelIdx;
/// <summary>
/// the physical channel index of the channel among channels on the DAS
/// </summary>
public int ChannelIdx
{
get => _channelIdx;
set => SetProperty(ref _channelIdx, value, "ChannelIdx");
}
/// <summary>
/// BitMask indicating the supported bridges on a das by default (half (4) + full (8))bridge
/// </summary>
public const int DEFAULT_SUPPORTED_BRIDGES = 12;
private int _supportedBridges = DEFAULT_SUPPORTED_BRIDGES;
/// <summary>
/// BitMask for bridges supported by the channel
/// Bit 0 indicates IEPE
/// Bit 1 indicates quarter bridge
/// Bit 2 indicates half bridge
/// Bit 3 indicates full bridge
/// Bit 4 indicates digital input
/// Bit 5 indicates squib fire
/// Bit 6 indicates digital output
/// Bit 7 indicates Half bridge signal plus (G5 signal plus)
/// Bit 8 indicates RealTime Clock
/// Bit 9 indicates UART
/// </summary>
public int SupportedBridges
{
get => _supportedBridges;
set => SetProperty(ref _supportedBridges, value, "SupportedBridges");
}
/// <summary>
/// BitMask indicating the supported excitations for a das channel by default
/// (5V by default)
/// </summary>
public const int DEFAULT_SUPPORTED_EXCITATIONS = 16;
private int _supporedExcitations = DEFAULT_SUPPORTED_EXCITATIONS;
/// <summary>
/// BitMask indicating what excitation options the channel supports
/// Bit 0 indicates an invalid excitation (undefined)
/// Bit 1 indicates 2V
/// Bit 2 indicates 2.5V
/// Bit 3 indicates 3V
/// Bit 4 indicates 5V
/// Bit 5 indicates 10V
/// Bit 6 indicates 1V
/// </summary>
public int SupportedExcitations
{
get => _supporedExcitations;
set => SetProperty(ref _supporedExcitations, value, "SupportedExcitations");
}
[Column("DASDisplayOrder")]
private int _dasDisplayOrder;
/// <summary>
/// The display order of the channel among channels on the DAS
/// note that the physical order of channels and the display order may not match for
/// some hardware
/// </summary>
public int DASDisplayOrder
{
get => _dasDisplayOrder;
set => SetProperty(ref _dasDisplayOrder, value, "DASDisplayOrder");
}
private bool _bLocalOnly;
/// <summary>
/// Indicates that record should be stored only in the local db and not propagated to a central db
/// deprecated
/// </summary>
public bool LocalOnly
{
get => _bLocalOnly;
set => SetProperty(ref _bLocalOnly, value, "LocalOnly");
}
/// <summary>
/// Bitmask indicating the default supported digital input modes for a channel (CCNC)
/// </summary>
public const int DEFAULT_SUPPORTED_DI_MODES = 16;
private int _supportedDigitalInputModes = DEFAULT_SUPPORTED_DI_MODES;
/// <summary>
/// BitMask indicating what Digital input modes are supported on the channel (if channel supports digital input bridge type)
/// Bit 0 indicates an invalid mode
/// Bit 1 indicates Transition low to high (TLH)
/// Bit 2 indicates Transition high to low (THL)
/// Bit 3 indicates Contact closure normally open (CCNO)
/// Bit 4 indicates Contact closure normally closed (CCNC)
/// </summary>
public int SupportedDigitalInputModes
{
get => _supportedDigitalInputModes;
set => SetProperty(ref _supportedDigitalInputModes, value, "SupportedDigitalInputModes");
}
/// <summary>
/// BitMask indicating the default squib fire modes supported by a channel (note that 16 is invalid, but
/// I'm preserving what is in the existing code)
/// </summary>
public const int DEFAULT_SQUIB_FIRE_MODES = 16;
private int _supportedSquibFireModes = DEFAULT_SQUIB_FIRE_MODES;
/// <summary>
/// BitMask indicating what Squib fire modes are supported on the channel (if the channel supports squib fire bridge type)
/// Bit 0 indicates an invalid mode (fire mode not set)
/// Bit 1 indicates capacitor discharge
/// Bit 2 indicates constant current
/// Bit 3 indicates AC discharge
/// </summary>
public int SupportedSquibFireModes
{
get => _supportedSquibFireModes;
set => SetProperty(ref _supportedSquibFireModes, value, "SupportedSquibFireModes");
}
/// <summary>
/// Default digital output mode for channels 16 doesn't exist, but I'm preserving the existing behavior values
/// </summary>
public const int DEFAULT_SUPPORTED_DO_MODES = 16;
private int _supportedDigitalOutputModes = DEFAULT_SUPPORTED_DO_MODES;
/// <summary>
/// BitMask indicating what digital output modes are supported on the channel (if the channel supports digital output bridge type)
/// Bit 0 indicates 5V low to high (FVLH)
/// Bit 1 indicates 5V high to low transition (FVHL)
/// Bit 2 indicates contact closure normally open (CCNO)
/// Bit 3 indicates contact closure normally closed (CCNC)
/// </summary>
public int SupportedDigitalOutputModes
{
get => _supportedDigitalOutputModes;
set => SetProperty(ref _supportedDigitalOutputModes, value, "SupportedDigitalOutputModes");
}
[StringLength(16)]
protected string _moduleSerialNumber = "";
/// <summary>
/// Serial number of module channel belongs to
/// </summary>
public string ModuleSerialNumber
{
get => _moduleSerialNumber;
set => SetProperty(ref _moduleSerialNumber, value, "ModuleSerialNumber");
}
public int SettingId { get; set; }
protected int _moduleArrayIndex;
/// <summary>
/// Array index of module among modules on a DAS or Rack
/// </summary>
public int ModuleArrayIndex
{
get => _moduleArrayIndex;
set => _moduleArrayIndex = value;
}
public DASChannelDBRecord() { }
/// <summary>
/// constructor using a datareader to retrieve values
/// </summary>
/// <param name="reader"></param>
public DASChannelDBRecord(IDataReader reader)
{
HardwareId = Utility.GetString(reader, "HardwareId", string.Empty);
ChannelIdx = Utility.GetInt(reader, "ChannelIdx", -1);
SupportedBridges = Utility.GetInt(reader, "SupportedBridges", DEFAULT_SUPPORTED_BRIDGES);
SupportedExcitations = Utility.GetInt(reader, "SupportedExcitations", DEFAULT_SUPPORTED_EXCITATIONS);
SupportedDigitalInputModes = Utility.GetInt(reader, "SupportedDigitalInputModes", DEFAULT_SUPPORTED_DI_MODES);
SupportedDigitalOutputModes = Utility.GetInt(reader, "SupportedDigitalOutputModes", DEFAULT_SUPPORTED_DO_MODES);
SupportedSquibFireModes = Utility.GetInt(reader, "SupportedSquibFireModes", DEFAULT_SQUIB_FIRE_MODES);
DASDisplayOrder = Utility.GetInt(reader, "DASDisplayOrder", 0);
ModuleSerialNumber = Utility.GetString(reader, "ModuleSerialNumber", string.Empty);
LocalOnly = Utility.GetBool(reader, "LocalOnly", false);
ModuleArrayIndex = Utility.GetInt(reader, "ModuleArrayIndex", -1);
}
/// <summary>
/// copy constructor
/// </summary>
/// <param name="copy"></param>
public DASChannelDBRecord(IDASChannelDBRecord copy)
{
HardwareId = copy.HardwareId;
ChannelIdx = copy.ChannelIdx;
SupportedBridges = copy.SupportedBridges;
SupportedExcitations = copy.SupportedExcitations;
SupportedDigitalInputModes = copy.SupportedDigitalInputModes;
SupportedDigitalOutputModes = copy.SupportedDigitalOutputModes;
SupportedSquibFireModes = copy.SupportedSquibFireModes;
DASDisplayOrder = copy.DASDisplayOrder;
ModuleSerialNumber = copy.ModuleSerialNumber;
LocalOnly = copy.LocalOnly;
ModuleArrayIndex = copy.ModuleArrayIndex;
}
}
}

View File

@@ -0,0 +1,201 @@
using DTS.Common.Base;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DataRecorders;
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Linq;
using System.Text;
namespace DTS.Common.Classes.Hardware
{
[Table("DAS")]
/// <summary>
/// Implementation of <seealso cref="IDASDBRecord"/>
/// <inheritdoc cref="IDASDBRecord"/>
/// </summary>
public class DASDBRecord : BasePropertyChanged, IDASDBRecord
{
public static DateTime INVALID_DATE => new DateTime(1970, 1, 1);
public DASDBRecord()
{
}
public DASDBRecord(IDASDBRecord copy)
{
CalDate = copy.CalDate;
Connection = copy.Connection;
Channels = copy.Channels;
FirmwareVersion = copy.FirmwareVersion;
LastModified = copy.LastModified;
LastModifiedBy = copy.LastModifiedBy;
LastUsed = copy.LastUsed;
LastUsedBy = copy.LastUsedBy;
LocalOnly = copy.LocalOnly;
MaxMemory = copy.MaxMemory;
MaxModules = copy.MaxModules;
MaxSampleRate = copy.MaxSampleRate;
MinSampleRate = copy.MinSampleRate;
Position = copy.Position;
IsReconfigurable = copy.IsReconfigurable;
IsModule = copy.IsModule;
IsProgrammable = copy.IsProgrammable;
ProtocolVersion = copy.ProtocolVersion;
SerialNumber = copy.SerialNumber;
DASType = copy.DASType;
DASId = copy.DASId;
var channelTypes = new int[copy.ChannelTypes.Length];
Array.Copy(copy.ChannelTypes, channelTypes, copy.ChannelTypes.Length);
ChannelTypes = channelTypes;
Version = copy.Version;
ParentDAS = copy.ParentDAS;
Port = copy.Port;
PositionOnChain = copy.PositionOnChain;
PositionOnDistributor = copy.PositionOnDistributor;
FirstUseDate = copy.FirstUseDate;
IsFirstUseValid = copy.IsFirstUseValid;
StandIn = copy.StandIn;
TestId = copy.TestId;
GroupId = copy.GroupId;
MaxAAFRate = copy.MaxAAFRate;
}
public DASDBRecord(IDataReader reader)
{
CalDate = Utility.GetDateTime(reader, "CalDate", DateTime.MinValue);
Connection = Utility.GetString(reader, "Connection", string.Empty);
Channels = Utility.GetInt(reader, "Channels", 0);
FirmwareVersion = Utility.GetString(reader, "FirmwareVersion", string.Empty);
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastModifiedBy = Utility.GetString(reader, "LastModifiedBy", string.Empty);
LastUsed = Utility.GetDateTime(reader, "LastUsed", DateTime.MinValue);
LastUsedBy = Utility.GetString(reader, "LastUsedBy", string.Empty);
LocalOnly = Utility.GetBool(reader, "LocalOnly", false);
MaxMemory = Utility.GetLong(reader, "MaxMemory", 0);
MaxModules = Utility.GetInt(reader, "MaxModules", 0);
MaxSampleRate = Utility.GetDouble(reader, "MaxSampleRate", 0);
MinSampleRate = Utility.GetDouble(reader, "MinSampleRate", 0);
Position = Utility.GetString(reader, "Position", string.Empty);
IsReconfigurable = Utility.GetBool(reader, "Reconfigurable", false);
IsModule = Utility.GetBool(reader, "IsModule", false);
IsProgrammable = Utility.GetBool(reader, "Reprogramable", false);
ProtocolVersion = Utility.GetInt(reader, "ProtocolVersion", 0);
SerialNumber = Utility.GetString(reader, "SerialNumber", string.Empty);
DASType = Utility.GetInt(reader, "Type", -1);
DASId = Utility.GetInt(reader, "DASId", -1);
var o = reader["ChannelTypes"];
if (null != o && !DBNull.Value.Equals(o))
{
var s = Utility.GetString(reader, "ChannelTypes", string.Empty);
var tokens = s.Split(new char[] { ',' });
var itemp = 0;
ChannelTypes = (from token in tokens where int.TryParse(token, out itemp) select itemp).ToArray();
}
Version = Utility.GetInt(reader, "Version", 0);
ParentDAS = Utility.GetString(reader, "ParentDAS", string.Empty);
Port = Utility.GetInt(reader, "Port", 0);
PositionOnChain = Utility.GetInt(reader, "PositionOnChain", 0);
PositionOnDistributor = Utility.GetInt(reader, "PositionOnDistributor", 0);
o = reader["FirstUseDate"];
if (DBNull.Value.Equals(o))
{
FirstUseDate = null;
IsFirstUseValid = false;
}
else
{
var dt = Convert.ToDateTime(o);
if (dt.Year.Equals(DFConstantsAndEnums.FIRST_USE_DATE_NOT_SET.Year))
{
FirstUseDate = null;
}
else
{
FirstUseDate = dt;
}
IsFirstUseValid = true;
}
StandIn = Utility.GetBool(reader, "StandIn", false);
TestId = Utility.GetNullableInt(reader, "TestId");
GroupId = Utility.GetNullableInt(reader, "GroupId");
MaxAAFRate = Utility.GetDouble(reader, "MaxAAFRate", double.NaN);
}
[Key]
[Column("DASId")]
public int DASId { get; set; }
[Required]
[StringLength(50)]
public string SerialNumber { get; set; }
public int DASType { get; set; }
public int MaxModules { get; set; }
public long MaxMemory { get; set; }
[Column(TypeName = "decimal(18, 0)")]
public double MaxSampleRate { get; set; }
[Column(TypeName = "decimal(18, 0)")]
public double MinSampleRate { get; set; }
[StringLength(50)]
public string FirmwareVersion { get; set; } = "";
[Column(TypeName = "datetime")]
public DateTime CalDate { get; set; } = INVALID_DATE;
public int ProtocolVersion { get; set; }
[Column(TypeName = "datetime")]
public DateTime LastModified { get; set; }
[StringLength(50)]
public string LastModifiedBy { get; set; } = "";
public int Version { get; set; }
public bool LocalOnly { get; set; }
[Column(TypeName = "datetime")]
public DateTime LastUsed { get; set; } = INVALID_DATE;
[StringLength(50)]
public string LastUsedBy { get; set; } = "";
[StringLength(50)]
public string Connection { get; set; } = "";
public int Channels { get; set; }
[Required]
[StringLength(50)]
public string Position { get; set; } = "";
[StringLength(255)]
public int[] ChannelTypes { get; set; } = new int[0];
public bool IsProgrammable { get; set; } = false;
public bool IsReconfigurable { get; set; } = false;
public bool IsModule { get; set; }
public int PositionOnDistributor { get; set; }
public int PositionOnChain { get; set; }
public int Port { get; set; }
[Column("ParentDAS")]
[StringLength(50)]
public string ParentDAS { get; set; } = "";
[Column(TypeName = "datetime")]
public DateTime? FirstUseDate { get; set; }
public int? TestId { get; set; }
public int? GroupId { get; set; }
public bool StandIn { get; set; }
[Column("MaxAAFRate", TypeName = "decimal(18, 0)")]
public double MaxAAFRate { get; set; }
/// <summary>
/// whether hardware supports and is using first use date
/// 15524 DAS "First Use Date"
/// </summary>
public bool IsFirstUseValid { get; set; } = false;
}
}

View File

@@ -0,0 +1,359 @@
using DTS.Common.Enums;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Interface.Hardware;
using DTS.Common.Utilities.Logging;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
namespace DTS.Common.Classes.Hardware
{
public class DASMonitorInfo : IDASMonitorInfo
{
public string SerialNumber { get; private set; }
public double[] TiltSensorCals { get; private set; } = new double[18];
public short[] TiltSensorDataPre { get; private set; } = new short[3];
public DFConstantsAndEnums.TiltAxes TiltAxes { get; private set; } = DFConstantsAndEnums.TiltAxes.IXIYIZ;
public int AxisIgnored { get; private set; }
public double MountOffsetAxisOne { get; private set; } = double.NaN;
public double MountOffsetAxisTwo { get; private set; } = double.NaN;
private string[] _channelNames = new string[0];
public string GetChannelName(int index)
{
if (index >= _channelNames.Length) { return $"{Strings.Strings.Ch}#{1 + index:00}"; }
return _channelNames[index];
}
private double[] _offsetTolerancesHigh = new double[6];
public double GetOffsetTolerancemVHigh(int index)
{
if (index >= _offsetTolerancesHigh.Length) { return 0D; }
return _offsetTolerancesHigh[index];
}
private double[] _offsetTolerancesLow = new double[6];
public double GetOffsetTolerancemVLow(int index)
{
if (index >= _offsetTolerancesLow.Length) { return 0D; }
return _offsetTolerancesLow[index];
}
public void ReadFromFile(string path)
{
if (!File.Exists(path)) { return; }
try
{
var lines = File.ReadAllLines(path);
var keys = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
for (var i = 0; i < lines.Length && i < keys.Length; i++)
{
var line = lines[i];
var key = keys[i];
switch (key)
{
case Fields.SerialNumber:
SerialNumber = line;
break;
case Fields.TiltSensorCals:
TiltSensorCals = ToDoubleArray(line);
break;
case Fields.TiltSensorDataPre:
TiltSensorDataPre = ToShortArray(line);
break;
case Fields.TiltAxes:
TiltAxes = (DFConstantsAndEnums.TiltAxes)Enum.Parse(typeof(DFConstantsAndEnums.TiltAxes), line);
break;
case Fields.AxesIgnored:
AxisIgnored = int.Parse(line, CultureInfo.InvariantCulture);
break;
case Fields.MountOffsetAxisOne:
MountOffsetAxisOne = double.Parse(line, CultureInfo.InvariantCulture);
break;
case Fields.MountOffsetAxisTwo:
MountOffsetAxisTwo = double.Parse(line, CultureInfo.InvariantCulture);
break;
case Fields.ChannelNames:
_channelNames = ToStringArray(line);
break;
case Fields.OffsetTolerancesLow:
_offsetTolerancesLow = ToDoubleArray(line);
break;
case Fields.OffsetTolerancesHigh:
_offsetTolerancesHigh = ToDoubleArray(line);
break;
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
private short[] ToShortArray(string line)
{
var shorts = new List<short>();
var tokens = line.Split(new[] { SEPARATOR }, StringSplitOptions.None);
foreach (var token in tokens)
{
if (short.TryParse(line, NumberStyles.Any, CultureInfo.InvariantCulture, out var s))
{
shorts.Add(s);
}
}
return shorts.ToArray();
}
private string[] ToStringArray(string line)
{
return line.Split(new[] { SEPARATOR }, StringSplitOptions.None);
}
private double[] ToDoubleArray(string line)
{
var doubles = new List<double>();
var tokens = line.Split(new[] { SEPARATOR }, StringSplitOptions.None);
foreach (var token in tokens)
{
if (double.TryParse(token, NumberStyles.Any, CultureInfo.InvariantCulture, out double d))
{
doubles.Add(d);
}
}
return doubles.ToArray();
}
private const string SEPARATOR = ",";
public void WriteToFile(string path)
{
try
{
var lines = new List<string>();
var keys = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
foreach (var key in keys)
{
switch (key)
{
case Fields.SerialNumber:
lines.Add(SerialNumber);
break;
case Fields.TiltSensorCals:
lines.Add(ToString(TiltSensorCals));
break;
case Fields.TiltSensorDataPre:
lines.Add(ToString(TiltSensorDataPre));
break;
case Fields.TiltAxes:
lines.Add(TiltAxes.ToString());
break;
case Fields.AxesIgnored:
lines.Add(AxisIgnored.ToString());
break;
case Fields.MountOffsetAxisOne:
lines.Add(MountOffsetAxisOne.ToString(CultureInfo.InvariantCulture));
break;
case Fields.MountOffsetAxisTwo:
lines.Add(MountOffsetAxisTwo.ToString(CultureInfo.InvariantCulture));
break;
case Fields.ChannelNames:
lines.Add(ToString(_channelNames));
break;
case Fields.OffsetTolerancesLow:
lines.Add(ToString(_offsetTolerancesLow));
break;
case Fields.OffsetTolerancesHigh:
lines.Add(ToString(_offsetTolerancesHigh));
break;
}
}
File.WriteAllLines(path, lines.ToArray());
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
private string ToString(string[] values)
{
return string.Join(SEPARATOR, values);
}
private string ToString(double[] values)
{
var l = new List<string>();
foreach (var val in values)
{
l.Add(val.ToString(CultureInfo.InvariantCulture));
}
return ToString(l.ToArray());
}
private string ToString(short[] values)
{
var l = new List<string>();
foreach (var val in values)
{
l.Add(val.ToString(CultureInfo.InvariantCulture));
}
return ToString(l.ToArray());
}
private enum Fields
{
SerialNumber,
TiltSensorCals,
TiltSensorDataPre,
TiltAxes,
AxesIgnored,
MountOffsetAxisOne,
MountOffsetAxisTwo,
ChannelNames,
OffsetTolerancesLow,
OffsetTolerancesHigh
}
private double[] GetTiltSensorCals(IDASCommunication das)
{
return das is ITiltSensorCalAware iTiltAware ? iTiltAware.TiltSensorCals : (new double[0]);
}
private short[] GetTiltSensorData(IDASCommunication das)
{
return new short[] { 0, 0, 0 };
}
public DASMonitorInfo(IDASCommunication das, IsoViewMode mode)
{
var keys = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
foreach (var key in keys)
{
switch (key)
{
case Fields.SerialNumber:
SerialNumber = das.SerialNumber;
break;
case Fields.TiltSensorCals:
TiltSensorCals = GetTiltSensorCals(das);
break;
case Fields.TiltSensorDataPre:
TiltSensorDataPre = GetTiltSensorData(das);
break;
case Fields.TiltAxes:
TiltAxes = GetTiltAxes(das);
break;
case Fields.AxesIgnored:
AxisIgnored = GetAxisIgnored(das);
break;
case Fields.MountOffsetAxisOne:
MountOffsetAxisOne = GetMountOffsetAxisOne(das);
break;
case Fields.MountOffsetAxisTwo:
MountOffsetAxisTwo = GetMountOffsetAxisTwo(das);
break;
case Fields.ChannelNames:
_channelNames = GetChannelNames(das, mode);
break;
case Fields.OffsetTolerancesLow:
_offsetTolerancesLow = GetOffsetTolerancemVLow(das);
break;
case Fields.OffsetTolerancesHigh:
_offsetTolerancesHigh = GetOffsetTolerancemVHigh(das);
break;
}
}
}
private double[] GetOffsetTolerancemVHigh(IDASCommunication das)
{
if (NoModules(das)) { return new double[0]; }
var list = new List<double>();
foreach (var module in das.ConfigData.Modules)
{
foreach (var ch in module.Channels)
{
if (ch is IAnalogInputDASChannel aic)
{
list.Add(aic.OffsetToleranceHighMilliVolts);
}
else { list.Add(0); }
}
}
return list.ToArray();
}
private double[] GetOffsetTolerancemVLow(IDASCommunication das)
{
if (NoModules(das)) { return new double[0]; }
var list = new List<double>();
foreach (var module in das.ConfigData.Modules)
{
foreach (var ch in module.Channels)
{
if (ch is IAnalogInputDASChannel aic)
{
list.Add(aic.OffsetToleranceLowMilliVolts);
}
else { list.Add(0); }
}
}
return list.ToArray();
}
private bool NoModules(IDASCommunication das)
{
return null == das.ConfigData || null == das.ConfigData.Modules || 0 == das.ConfigData.Modules.Length;
}
private double GetMountOffsetAxisTwo(IDASCommunication das)
{
return NoModules(das) ? float.NaN : das.ConfigData.Modules[0].MountOffsetAxisTwo;
}
private double GetMountOffsetAxisOne(IDASCommunication das)
{
return NoModules(das) ? float.NaN : das.ConfigData.Modules[0].MountOffsetAxisOne;
}
private int GetAxisIgnored(IDASCommunication das)
{
return NoModules(das) ? 0 : das.ConfigData.Modules[0].AxisIgnored;
}
private DFConstantsAndEnums.TiltAxes GetTiltAxes(IDASCommunication das)
{
return NoModules(das) ? DFConstantsAndEnums.TiltAxes.IXIYIZ : das.ConfigData.Modules[0].TiltAxes;
}
private string[] GetChannelNames(IDASCommunication das, IsoViewMode viewMode)
{
if (NoModules(das)) { return new string[0]; }
var list = new List<string>();
foreach (var mod in das.ConfigData.Modules)
{
foreach (var ch in mod.Channels)
{
switch (viewMode)
{
case IsoViewMode.ISOOnly:
list.Add(ch.IsoChannelName);
break;
case IsoViewMode.ISOAndUserCode:
list.Add($"{ ch.IsoChannelName}\\{ch.UserChannelName}");
break;
case IsoViewMode.UserCodeOnly:
list.Add(ch.UserCode);
break;
case IsoViewMode.ChannelNameOnly:
list.Add(ch.UserChannelName);
break;
}
}
}
return list.ToArray();
}
public DASMonitorInfo(string path)
{
try
{
ReadFromFile(path);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
}
}

View File

@@ -0,0 +1,9 @@
namespace DTS.Common.Classes.Hardware
{
public class DragAndDropPayload
{
public const string FORMAT = "RESOLVECHANNELS_HARDWARETABLE";
public const string ALT_FORMAT = "ALT_RESOLVECHANNELS_HARDWARETABLE";
public const string CTRL_FORMAT = "CTRL_RESOLVECHANNELS_HARDWARETABLE";
}
}

View File

@@ -0,0 +1,11 @@
namespace DTS.Common.Classes.Hardware
{
public class ExternalTilt
{
public ExternalTilt() { }
public string SerialNumber { get; set; }
public byte TiltID { get; set; }
public string SystemID { get; set; }
public string SystemLocation { get; set; }
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DTS.Common.Classes.Hardware
{
public class SerializableAAF
{
public enum DAS_TYPE { TDAS = 0, SLICE = 1 };
/*private DAS_TYPE _type = DAS_TYPE.TDAS;
public DAS_TYPE DasType { get { return _type; } }
private UInt64 _sampleRate = 0;
public UInt64 SampleRate { get { return _sampleRate; } }
private float _aaf = 0F;
public float AAF { get { return _aaf; } }
public SerializableAAF(DAS_TYPE type, ulong sps, float aaf)
{
_type = type;
_sampleRate = sps;
_aaf = aaf;
}
private const string SEPARATOR = "_x_";
public string GetSerializedKey()
{
return string.Format("{0}{1}{2}", (int)DasType, SEPARATOR, SampleRate);
}
public string GetSerializedValue()
{
return AAF.ToString(System.Globalization.CultureInfo.InvariantCulture);
}
public void FromSerializedStrings(string key, string value)
{
string[] tokens = key.Split(new string[] { SEPARATOR }, StringSplitOptions.None);
if (2 != tokens.Length) { throw new NotSupportedException("Invalid Format AAF key: " + key.ToArray()); }
_type = (DAS_TYPE)Convert.ToInt32(tokens[0]);
_sampleRate = Convert.ToUInt64(tokens[1]);
_aaf = Convert.ToSingle(value);
}*/
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTS.Common.Events;
using DTS.Common.Interface.ISO.ExtraProperties;
namespace DTS.Common.ISO.ExtraProperties
{
public class TextPastedArgs : ITextPastedEventArgs
{
public string Text { get; }
public object Sender { get; }
public string Id { get; }
public object Tag { get; }
public TextPastedArgs(string text, IExtraProperty extraProperty, string id, object tag)
{
Text = text;
Sender = extraProperty;
Id = id;
Tag = tag;
}
}
}

View File

@@ -0,0 +1,202 @@
using System.Text;
namespace DTS.Common.ISO
{
public class IsoCode
{
private readonly char[] _isoCodeFull = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' };
private char _testObject
{
get => _isoCodeFull[0];
set => _isoCodeFull[0] = value;
}
public string TestObject
{
get => new string(new[] { _testObject });
set => _testObject = string.IsNullOrEmpty(value) ? '?' : value[0];
}
private char _position
{
get => _isoCodeFull[1];
set => _isoCodeFull[1] = value;
}
public string Position
{
get => new string(new[] { _position });
set => _position = string.IsNullOrEmpty(value) ? '?' : value[0];
}
private char[] _mainLocation
{
get => new[] { _isoCodeFull[2], _isoCodeFull[3], _isoCodeFull[4], _isoCodeFull[5] };
set
{
for (var i = 0; i < 4; i++)
{
if (value.Length <= i) { _isoCodeFull[i + 2] = '0'; }
else { _isoCodeFull[i + 2] = value[i]; }
}
}
}
public string MainLocation
{
get => new string(_mainLocation);
set
{
var main = value;
if (main.Length < 4) { main = main.PadRight(4, '?'); }
else if (main.Length > 4) { main = main.Substring(0, 4); }
_mainLocation = main.ToCharArray(0, 4);
}
}
private char[] _fineLocation1
{
get => new[] { _isoCodeFull[6], _isoCodeFull[7] };
set
{
for (var i = 0; i < 2; i++)
{
_isoCodeFull[i + 6] = value.Length < i ? '0' : value[i];
}
}
}
public string FineLocation1
{
get => new string(_fineLocation1);
set
{
var loc = value;
if (loc.Length < 2) { loc = loc.PadRight(2, '?'); }
_fineLocation1 = loc.ToCharArray(0, 2);
}
}
private char[] _fineLocation2
{
get => new[] { _isoCodeFull[8], _isoCodeFull[9] };
set
{
for (var i = 0; i < 2; i++)
{
if (value.Length < i) { _isoCodeFull[i + 8] = '0'; }
else { _isoCodeFull[i + 8] = value[i]; }
}
}
}
public string FineLocation2
{
get => new string(_fineLocation2);
set
{
var loc = value;
if (loc.Length < 2) { loc = loc.PadRight(2, '?'); }
_fineLocation2 = loc.ToCharArray(0, 2);
}
}
private char[] _fineLocation3
{
get => new[] { _isoCodeFull[10], _isoCodeFull[11] };
set
{
for (var i = 0; i < 2; i++)
{
if (value.Length < i) { _isoCodeFull[i + 10] = '0'; }
else { _isoCodeFull[i + 10] = value[i]; }
}
}
}
public string FineLocation3
{
get => new string(_fineLocation3);
set
{
var loc = value;
if (loc.Length < 2) { loc = loc.PadRight(2, '?'); }
_fineLocation3 = loc.ToCharArray(0, 2);
}
}
private char[] _physicalDimension
{
get => new[] { _isoCodeFull[12], _isoCodeFull[13] };
set
{
for (var i = 0; i < 2; i++)
{
if (value.Length < i) { _isoCodeFull[i + 12] = '0'; }
else { _isoCodeFull[i + 12] = value[i]; }
}
}
}
public string PhysicalDimension
{
get => new string(_physicalDimension);
set
{
var dim = value;
if (dim.Length < 2) { dim = dim.PadRight(2, '?'); }
else if (dim.Length > 2) { dim = dim.Substring(0, 2); }
_physicalDimension = dim.ToCharArray(0, 2);
}
}
private char _direction
{
get => _isoCodeFull[14];
set => _isoCodeFull[14] = value;
}
public string Direction
{
get => new string(new[] { _direction });
set
{
if (string.IsNullOrEmpty(value)) { _direction = '?'; }
else { _direction = value[0]; }
}
}
private char _filterClass
{
get => _isoCodeFull[15];
set => _isoCodeFull[15] = value;
}
public string FilterClass
{
get => new string(new[] { _filterClass });
set => _filterClass = string.IsNullOrEmpty(value) ? '?' : value[0];
}
public IsoCode(string isoCode)
{
if (null == isoCode) { isoCode = ""; }
if (isoCode.Length > 16) { isoCode = isoCode.Substring(0, 16); }
if (isoCode.Length < 16)
{
isoCode = isoCode.PadRight(16, '?');
}
for (var i = 0; i < 16; i++) { _isoCodeFull[i] = isoCode[i]; }
}
public string StringRepresentation
{
get
{
var sb = new StringBuilder();
foreach (var c in _isoCodeFull) { sb.Append(c); }
return sb.ToString();
}
set
{
for (var i = 0; i < 16; i++)
{
if (i >= value.Length) { _isoCodeFull[i] = '0'; }
else { _isoCodeFull[i] = value[i]; }
}
}
}
}
}

View File

@@ -0,0 +1,53 @@
using DTS.Common.Enums;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.Sensors;
using System;
using System.Collections.Generic;
namespace DTS.Common.Classes
{
public enum ImportPageType
{
ImportSensor,
ImportTestSetup
}
public class SensorImportData
{
public Dictionary<string, List<string>> GroupNameSensorListLookup { get; set; } = new Dictionary<string, List<string>>();
public Dictionary<string, string> SensorGroupNameLookup { get; set; } = new Dictionary<string, string>();
public Dictionary<string, string> SensorGroupTypeLookup { get; set; } = new Dictionary<string, string>();
public Dictionary<string, string> GroupNameTestObjectLookup { get; set; } = new Dictionary<string, string>();
public List<string> Errors { get; set; } = new List<string>();
public Dictionary<string, string> SensorISOCode { get; set; } = new Dictionary<string, string>();
public Dictionary<string, string> SensorISOChannelName { get; set; } = new Dictionary<string, string>();
public Dictionary<string, string> SensorUserCode { get; set; } = new Dictionary<string, string>();
public Dictionary<string, string> SensorUserChannelName { get; set; } = new Dictionary<string, string>();
public Dictionary<string, string> SensorDASSerialNumber { get; set; } = new Dictionary<string, string>();
public Dictionary<string, int> SensorChannelIndex { get; set; } = new Dictionary<string, int>();
}
public class TestSetupImportData
{
public string Name { get; set; }
public string Description { get; set; }
public double SamplesPerSecond { get; set; }
public double PosttriggerSeconds { get; set; }
public double PretriggerSeconds { get; set; }
public RecordingModes RecordingMode { get; set; }
public CalibrationBehaviors CalibrationBehavior { get; set; }
public int Version { get; set; }
public List<string> TestChannelOrders { get; set; }
public List<string> Tags { get; set; }
public InputClockSource ClockMasterInput { get; set; } = InputClockSource.None;
public OutputClockSource ClockMasterOutput { get; set; } = OutputClockSource.None;
public bool ManageClocksOutsideOfDataPROMaster { get; set; } = false;
public bool ManageClocksOutsideOfDataPROSlave { get; set; } = false;
public OutputClockSource ClockSlaveInput { get; set; } = OutputClockSource.None;
public OutputClockSource ClockSlaveOutput { get; set; } = OutputClockSource.None;
public Dictionary<string, int> SampleRateForDAS { get; } = new Dictionary<string, int>();
public Dictionary<string, uint> DomainIdForDAS { get; } = new Dictionary<string, uint>();
public Dictionary<string, bool> IsClockMaster { get; } = new Dictionary<string, bool>();
}
}

View File

@@ -0,0 +1,36 @@
namespace DTS.Common.Classes.Locking
{
public class LockError
{
public int ErrorCode { get; private set; }
public string Message { get; private set; }
public string LockingUser { get; private set; }
public string LockingMachine { get; private set; }
public bool LockStolen => ErrorCode == LOCKSTOLEN_ERROR;
public bool LockLost => ErrorCode == LOCKDOESNTEXIST_ERROR;
public override string ToString()
{
return $"{ErrorCode} - {Message}";
}
public LockError(int error, string message, string user = null, string machine = null)
{
ErrorCode = error;
Message = message;
LockingUser = user ?? string.Empty;
LockingMachine = machine ?? string.Empty;
}
//14782 Improve lost remote db connection modal dialogs
//this can apparently be returned by sqlclient on failed lock maintenance issues
public const int BAD_NETPATH_ERROR = 994;
//14782 Improve lost remote db connection modal dialogs
//system error of semaphore timeout, returned by sqlclient on failed to connect issues
public const int SEM_TIMEOUT_ERROR = 995;
public const int ITEM_NOT_FOUND = 996;
public const int LOCKDOESNTEXIST_ERROR = 997;
public const int LOCKSTOLEN_ERROR = 998;
public const int UNKNOWN_ERROR = 999;
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Data;
namespace DTS.Common.Classes.Locking
{
public class LockRecord
{
public string LockingUserName { get; }
public string LockingMachineName { get; }
public DateTime CreationTime { get; }
public DateTime LastUpdated { get; }
public string ItemKey { get; }
/// <summary>
/// this is the item category (as a value in the db - LockCategories)
/// </summary>
public int ItemCategory { get; }
public int ItemId { get; }
public LockRecord(string user, string machine, DateTime createTime, DateTime lastUpdate, string itemKey, int itemCategory, int itemId)
{
LockingUserName = user;
LockingMachineName = machine;
CreationTime = createTime;
LastUpdated = lastUpdate;
ItemKey = itemKey;
ItemCategory = itemCategory;
ItemId = itemId;
}
}
}

View File

@@ -0,0 +1,191 @@
using DTS.Common.Events;
using DTS.Common.SharedResource.Strings;
using DTS.Common.Utilities.Logging;
using Prism.Events;
using Prism.Events;
using Prism.Ioc;
using System;
using System.Collections.Generic;
using System.Drawing.Text;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Interop;
namespace DTS.Common.Classes.Locking
{
public class SensorsLocking
{
private LockRecord[] _existingLocks = null;
private static readonly object MyLock = new object();
private CancellationTokenSource _cancellationTokenSource = null;
private readonly Task _updateTask = null;
private const int MAX_WAIT_TIME_MS = 10000;
/// <summary>
/// returns false if stop was not needed or failed
/// returns true if stop was completed
/// </summary>
/// <returns></returns>
private bool StopUpdating()
{
if (null == _cancellationTokenSource || null == _existingLocks) { return false; }
lock (MyLock)
{
_cancellationTokenSource.Cancel();
if (!_updateTask.Wait(MAX_WAIT_TIME_MS))
{
APILogger.Log("Failed to stop updating locks");
return false;
}
}
return true;
}
public void Unlock(bool bCheckLock, string userName, int userId)
{
if (!StopUpdating()) { return; }
lock (MyLock)
{
if (null == _existingLocks || 0 == _existingLocks.Length) { return; }
}
try
{
FreeLocks();
}
catch (Exception ex) { APILogger.Log(ex); }
}
private void FreeLocks()
{
LockRecord[] locks;
lock (MyLock)
{
if (null == _existingLocks || 0 == _existingLocks.Length) { return; }
locks = _existingLocks.ToArray();
}
foreach( var record in locks)
{
try
{
LockManager.FreeLoc
}
catch(Exception ex) { APILogger.Log(ex); }
}
}
private bool CheckLock(bool publishErrors, string userName, int userId, LockRecord lockRecord, out LockError lockError)
{
throw new NotImplementedException();
}
/// <summary>
/// performs an immediate update of locks, publishes an error if the lock could not be updated
/// </summary>
/// <param name="publishErrors">whether to publish when there's an error or not</param>
/// <returns></returns>
private bool CheckLocks(bool publishErrors, string userName, int userId)
{
try
{
LockRecord[] records;
lock (MyLock)
{
//FB 18006 Prevent null reference exception
if (_existingLocks == null || 0 == _existingLocks.Length)
{
APILogger.Log("_existingLock is null");
return false;
}
//create a local copy of the locks so we can update them without the lock
records = _existingLocks.ToArray();
}
var failed = new List<LockRecord>();
var errors = new List<LockError>();
foreach (var record in records)
{
LockError lockError;
if (!CheckLock(publishErrors, userName, userId, record, out lockError))
{
failed.Add(record);
errors.Add(lockError);
}
}
if (failed.Any() && errors.Any())
{
if (publishErrors)
{
var msg = GetErrorMessage(errors.ToArray(), records.ToArray());
var eventAggregator = ContainerLocator.Container.Resolve<IEventAggregator>();
eventAggregator.GetEvent<PageErrorEvent>().Publish(new PageErrorArg(new[] { msg }, null));
}
//if we failed to update ANY of them we need to wipe out our selection
lock (MyLock)
{
_existingLocks = new LockRecord[0];
}
WipeOutChanges();
return false;
}
return true;
}
catch (Exception ex)
{
APILogger.Log(ex);
if (publishErrors)
{
var eventAggregator = ContainerLocator.Container.Resolve<IEventAggregator>();
eventAggregator.GetEvent<PageErrorEvent>().Publish(new PageErrorArg(
new[] { $"{StringResources.FailedToUpdateLock}, {ex.Message}" }, null));
}
_cancellationTokenSource?.Cancel();
lock (MyLock)
{
_existingLocks = new LockRecord[0];
}
return false;
}
}
private void WipeOutChanges()
{
throw new NotImplementedException();
}
private static string GetErrorMessage(LockError[] errors, LockRecord[] lockRecords )
{
StringBuilder sb = new StringBuilder(0);
for( var i = 0; i < errors.Length && i < lockRecords.Length; i ++)
{
var error = errors[i];
var record = lockRecords[i];
if (error.LockStolen)
{
sb.AppendLine(string.Format(StringResources.LockStolen_Sensors, record.ItemKey, error.LockingUser, error.LockingMachine));
}
else if(error.LockLost)
{
sb.AppendLine(string.Format(StringResources.LockLost_Sensors, record.ItemKey));
}
else
{
sb.AppendLine($"{StringResources.FailedToUpdateLock} - {record.ItemKey}");
}
}
return sb.ToString();
}
/// <summary>
/// returns true if the lockrecord matches the sensor currently locked in this control
/// 14340 sensor lost/locked - unlocked on sensor import
/// </summary>
/// <param name="lockRecord"></param>
/// <returns></returns>
public bool IsCurrentlyLocked(LockRecord lockRecord)
{
lock (MyLock)
{
if (null == _existingLocks) { return false; }
return Array.Exists(_existingLocks, x => x.ItemId == lockRecord.ItemId && x.ItemCategory == lockRecord.ItemCategory);
}
}
}
}

View File

@@ -0,0 +1,55 @@
namespace DTS.Common.Classes
{ /// <summary>
/// Provides the region names.
/// </summary>
public static class RegionNames
{
public const string FrontRegion = "FrontRegion";
public const string MainRegion = "MainRegion";
public const string ViewerEuRegion = "ViewerEuRegion";
public const string ViewerMvRegion = "ViewerMvRegion";
public const string ViewerEdcRegion = "ViewerEdcRegion";
public const string ViewerTestsRegion = "ViewerTestsRegion";
public const string ViewerGraphRegion = "ViewerGraphRegion";
public const string ViewerGraphsRegion = "ViewerGraphsRegion";
public const string ViewerGraphMainRegion = "ViewerGraphMainRegion";
public const string ViewerGraphListRegion = "ViewerGraphListRegion";
public const string ViewerGraphChannelRegion = "ViewerGraphChannelRegion";
public const string ViewerTestModificationRegion = "ViewerTestModificationRegion";
public const string ViewerLegendRegion = "ViewerLegendRegion";
public const string ViewerSearchRegion = "ViewerSearchRegion";
public const string ViewerSettingsRegion = "ViewerSettingsRegion";
public const string ViewerDiagRegion = "ViewerDiagRegion";
public const string ViewerDisplayRegion = "ViewerDisplayRegion";
public const string ViewerChartOptionsRegion = "ViewerChartOptionsRegion";
public const string ViewerStatsRegion = "ViewerStatsRegion";
public const string ViewerCursorRegion = "ViewerCursorRegion";
public const string ViewerFiterRegion = "ViewerFiterRegion";
public const string MenuRegion = "MenuRegion";
public const string NavigationRegion = "NavigationRegion";
public const string BottomRegion = "BottomRegion";
public const string RightRegion = "RightRegion";
public const string TopRegion = "TopRegion";
public const string VerticalTabRegion = "VerticalTabRegion";
public const string HorizontalTabRegion = "HorizontalTabRegion";
public const string RibbonRegion = "RibbonRegion";
public const string PropertyDisplayRegion = "PropertyDisplayRegion";
public const string PropertyModifyRegion = "PropertyModifyRegion";
public const string PropertyAddRegion = "PropertyAddRegion";
public const string PSDDataSelectRegion = "PSDDataSelectRegion";
public const string PSDGraphRegion = "PSDGraphRegion";
public const string ReportChartOptionsRegion = "ReportChartOptionsRegion";
public const string ReportResultsRegion = "ReportResultsRegion";
}
}

View File

@@ -0,0 +1,790 @@
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;
using System.Reflection;
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");
}
public bool InspectBeforeUseCleared { get; set; }
protected double _sensitivityTolerancePercent = Constants.SENSITIVITY_CHANGE_TOLERANCE_PERCENT_DEFAULT;
/// <summary>
///default SensitivityTolerancePercent
/// </summary>
public double SensitivityTolerancePercent
{
get => _sensitivityTolerancePercent;
set => SetProperty(ref _sensitivityTolerancePercent, value, "SensitivityTolerancePercent");
}
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");
}
private string _assemblyName = string.Empty;
public string AssemblyName
{
get => _assemblyName;
set => SetProperty(ref _assemblyName, value, "AssemblyName");
}
private int _usageCount = 0;
public int UsageCount
{
get => _usageCount;
set => SetProperty(ref _usageCount, value, "UsageCount");
}
private int _maximumUsage = 2500;
public int MaximumUsage
{
get => _maximumUsage;
set => SetProperty(ref _maximumUsage, value, "MaximumUsage");
}
private bool _dontAllowDataCollectionIfOverused = false;
public bool DontAllowDataCollectionIfOverused
{
get => _dontAllowDataCollectionIfOverused;
set => SetProperty(ref _dontAllowDataCollectionIfOverused, value, "DontAllowDataCollectionIfOverused");
}
private int _sensorUsageWarningCount = 5;
public int SensorUsageWarningCount
{
get => _sensorUsageWarningCount;
set => SetProperty(ref _sensorUsageWarningCount, value, "SensorUsageWarningCount");
}
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;
//43046
SensitivityTolerancePercent = copy.SensitivityTolerancePercent;
Id = copy.Id;
FirstUseDate = copy.FirstUseDate;
LatestCalibrationId = copy.LatestCalibrationId;
ACCouplingModeEnabled = copy.ACCouplingModeEnabled;
AssemblyName = copy.AssemblyName;
UsageCount = copy.UsageCount;
MaximumUsage = copy.MaximumUsage;
}
public AnalogDbRecord(IDataReader reader, int actualDbVersion)
{
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);
if (actualDbVersion >= Constants.SENSOR_ASSEMBLY_DB_VERSION)
{
//43046
SensitivityTolerancePercent = Utility.GetDouble(reader, "SensitivityTolerancePercent", Constants.SENSITIVITY_CHANGE_TOLERANCE_PERCENT_DEFAULT);
AssemblyName = Utility.GetString(reader, "AssemblyName").Trim();
UsageCount = Utility.GetInt(reader, "UsageCount", 0);
MaximumUsage = Utility.GetInt(reader, "MaximumUsage", 2500);
}
}
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,115 @@
using DTS.Common.Interface.Sensors.AnalogDiagnostics;
using System;
using System.ComponentModel;
using System.Data.SqlClient;
namespace DTS.Common.Classes.Sensors.AnalogDiagnostics
{
public class DiagnosticEntry : IDiagnosticEntry
{
private long? _Id = null;
public long? Id { get => _Id; set => _Id = value; }
private long _DiagnosticRunId = -1;
public long DiagnosticRunId { get => _DiagnosticRunId; set => _DiagnosticRunId = value; }
private double? _Excitation = null;
public double? Excitation { get => _Excitation; set => _Excitation = value; }
private DiagnosticStatus _ExcitationStatus = DiagnosticStatus.Untested;
public DiagnosticStatus ExcitationStatus { get => _ExcitationStatus; set => _ExcitationStatus = value; }
private double? _Offset = null;
public double? Offset { get => _Offset; set => _Offset = value; }
private DiagnosticStatus _OffsetStatus = DiagnosticStatus.Untested;
public DiagnosticStatus OffsetStatus { get => _OffsetStatus; set => _OffsetStatus = value; }
private double? _ActualRange = null;
public double? ActualRange { get => _ActualRange; set => _ActualRange = value; }
private DiagnosticStatus _ActualRangeStatus = DiagnosticStatus.Untested;
public DiagnosticStatus ActualRangeStatus { get => _ActualRangeStatus; set => _ActualRangeStatus = value; }
private double? _Noise = null;
public double? Noise { get => _Noise; set => _Noise = value; }
private DiagnosticStatus _NoiseStatus = DiagnosticStatus.Untested;
public DiagnosticStatus NoiseStatus { get => _NoiseStatus; set => _NoiseStatus = value; }
private double? _Shunt = null;
public double? Shunt { get => _Shunt; set => _Shunt = value; }
private DiagnosticStatus _ShuntStatus = DiagnosticStatus.Untested;
public DiagnosticStatus ShuntStatus { get => _ShuntStatus; set => _ShuntStatus = value; }
private int? _SensorId;
public int? SensorId { get => _SensorId; set => _SensorId = value; }
private string _SensorSerialNumber = string.Empty;
public string SensorSerialNumber { get => _SensorSerialNumber; set => _SensorSerialNumber = value; }
private int? _DASId = null;
public int? DASId { get => _DASId; set => _DASId = value; }
private string _dasSerialNumber = string.Empty;
public string DASSerialNumber { get => _dasSerialNumber; set => _dasSerialNumber = value; }
private int _dasChannelIdx = 0;
public int DASChannelIdx { get => _dasChannelIdx; set => _dasChannelIdx = value; }
private string _UserCode = string.Empty;
public string UserCode { get => _UserCode; set => _UserCode = value; }
private string _UserChannelName = string.Empty;
public string UserChannelName { get => _UserChannelName; set => _UserChannelName = value; }
private string _IsoCode = string.Empty;
public string IsoCode { get => _IsoCode; set => _IsoCode = value; }
private string _IsoChannelName = string.Empty;
public string IsoChannelName { get => _IsoChannelName; set => _IsoChannelName = value; }
private double _scaleFactor = 1;
public double ScaleFactor { get => _scaleFactor; set => _scaleFactor = value; }
private int _calibrationRecordId = -1;
public int CalibrationRecordId { get => _calibrationRecordId; set => _calibrationRecordId = value; }
private string _calibrationRecordXML = string.Empty;
public string CalibrationRecordXML { get => _calibrationRecordXML; set => _calibrationRecordXML = value; }
private DateTime _timeStamp = DateTime.MinValue;
public DateTime Timestamp { get => _timeStamp; set => _timeStamp = value; }
public DiagnosticEntry() { }
public DiagnosticEntry (SqlDataReader reader)
{
if (!DBNull.Value.Equals(reader["Id"])) { Id = (long)reader["Id"]; }
if (!DBNull.Value.Equals(reader["DiagnosticRunId"])) { DiagnosticRunId = (long)reader["DiagnosticRunId"]; }
if (!DBNull.Value.Equals(reader["Excitation"])) { Excitation = (double)reader["Excitation"]; }
if (!DBNull.Value.Equals(reader["ExcitationStatus"])) { ExcitationStatus = (DiagnosticStatus)(short)reader["ExcitationStatus"]; }
if (!DBNull.Value.Equals(reader["Offset"])) { Offset = (double)reader["Offset"]; }
if (!DBNull.Value.Equals(reader["OffsetStatus"])) { OffsetStatus = (DiagnosticStatus)(short)reader["OffsetStatus"]; }
if (!DBNull.Value.Equals(reader["ActualRange"])) { ActualRange = (double)reader["ActualRange"]; }
if (!DBNull.Value.Equals(reader["ActualRangeStatus"])) { ActualRangeStatus = (DiagnosticStatus)(short)reader["ActualRangeStatus"]; }
if (!DBNull.Value.Equals(reader["Noise"])) { Noise = (double)reader["Noise"]; }
if (!DBNull.Value.Equals(reader["NoiseStatus"])) { NoiseStatus = (DiagnosticStatus)(short)reader["NoiseStatus"]; }
if (!DBNull.Value.Equals(reader["Shunt"])) { Shunt = (double)reader["Shunt"]; }
if (!DBNull.Value.Equals(reader["ShuntStatus"])) { ShuntStatus = (DiagnosticStatus)(short)reader["ShuntStatus"]; }
if (!DBNull.Value.Equals(reader["SensorId"])) { SensorId = (int)reader["SensorId"]; }
if (!DBNull.Value.Equals(reader["SensorSerialNumber"])) { SensorSerialNumber = (string)reader["SensorSerialNumber"]; }
if (!DBNull.Value.Equals(reader["DASId"])) { DASId = (int)reader["DASId"]; }
if (!DBNull.Value.Equals(reader["DASSerialNumber"])) { DASSerialNumber = (string)reader["DASSerialNumber"]; }
if (!DBNull.Value.Equals(reader["DASChannelIdx"])) { DASChannelIdx = (short)reader["DASChannelIdx"]; }
if (!DBNull.Value.Equals(reader["UserCode"])) { UserCode = (string)reader["UserCode"]; }
if (!DBNull.Value.Equals(reader["UserChannelName"])) { UserChannelName = (string)reader["UserChannelName"]; }
if (!DBNull.Value.Equals(reader["IsoCode"])) { IsoCode = (string)reader["IsoCode"]; }
if (!DBNull.Value.Equals(reader["IsoChannelName"])) { IsoChannelName = (string)reader["IsoChannelName"]; }
if (!DBNull.Value.Equals(reader["ScaleFactor"])) { ScaleFactor = (double)reader["ScaleFactor"]; }
if (!DBNull.Value.Equals(reader["CalibrationRecordId"])) { CalibrationRecordId = (int)reader["CalibrationRecordId"]; }
if (!DBNull.Value.Equals(reader["CalibrationRecordXML"])) { CalibrationRecordXML = (string)reader["CalibrationRecordXML"]; }
if (!DBNull.Value.Equals(reader["Timestamp"])) { Timestamp = (DateTime)reader["Timestamp"]; }
}
}
}

View File

@@ -0,0 +1,33 @@
using DTS.Common.Interface.Sensors.AnalogDiagnostics;
using System;
using System.Data.SqlClient;
namespace DTS.Common.Classes.Sensors.AnalogDiagnostics
{
public class DiagnosticRun : IDiagnosticRun
{
private long? _Id = null;
public long? Id { get => _Id; set => _Id = value; }
private string _DataPROUser = string.Empty;
public string DataPROUser { get => _DataPROUser; set => _DataPROUser = value; }
private int? _TestId = null;
public int? TestId { get => _TestId; set => _TestId = value; }
private string _TestName = string.Empty;
public string TestName { get => _TestName; set => _TestName = value; }
private bool _PreTest = true;
public bool PreTest { get => _PreTest; set => _PreTest = value; }
public DiagnosticRun() { }
public DiagnosticRun(SqlDataReader reader)
{
if (!DBNull.Value.Equals(reader["Id"])){ Id = (long)reader["Id"]; }
if (!DBNull.Value.Equals(reader["DataPROUser"])) { DataPROUser = (string)reader["DataPROUser"]; }
if (!DBNull.Value.Equals(reader["TestId"])) { TestId = (int)reader["TestId"]; }
if (!DBNull.Value.Equals(reader["TestName"])) { TestName = (string)reader["TestName"]; }
if (!DBNull.Value.Equals(reader["PreTest"])) { PreTest = (bool)reader["PreTest"]; }
}
}
}

View File

@@ -0,0 +1,130 @@
using DTS.Common.Interface.Sensors;
using DTS.Common.Interface.Tags;
using DTS.Common.Utilities.Logging;
using System;
using DTS.Common.Constant;
using System.Data;
namespace DTS.Common.Classes.Sensors
{
#pragma warning disable S101 // Types should be named in PascalCase
public class CANRecord : TagAwareBase, ICANRecord
#pragma warning restore S101 // Types should be named in PascalCase
{
public override TagTypes TagType { get => TagTypes.Sensors; }
private int _id;
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private string _serialNumber;
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
private DateTime _lastModified;
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private string _lastUpdatedBy;
public string LastUpdatedBy
{
get => _lastUpdatedBy;
set => SetProperty(ref _lastUpdatedBy, value, "LastUpdatedBy");
}
private bool _doNotUse;
public bool DoNotUse
{
get => _doNotUse;
set => SetProperty(ref _doNotUse, value, "DoNotUse");
}
private bool _broken;
public bool Broken
{
get => _broken;
set => SetProperty(ref _broken, value, "Broken");
}
private bool _canIsFD = EmbeddedSensors.CANISFD_DEFAULT;
public bool CanIsFD
{
get => _canIsFD;
set => SetProperty(ref _canIsFD, value, "CanIsFD");
}
private int _canArbBaseBitrate = EmbeddedSensors.CANFD_ARB_BASE_BITRATE_DEFAULT;
public int CanArbBaseBitrate
{
get => _canArbBaseBitrate;
set => SetProperty(ref _canArbBaseBitrate, value, "CanArbBaseBitrate");
}
private int _canArbBaseSJW = EmbeddedSensors.CANFD_1000000_ARB_BASE_SJW_MAX;
public int CanArbBaseSJW
{
get => _canArbBaseSJW;
set => SetProperty(ref _canArbBaseSJW, value, "CanArbBaseSJW");
}
private int _canDataBitrate = EmbeddedSensors.DATA_BITRATE_DEFAULT;
public int CanDataBitrate
{
get => _canDataBitrate;
set => SetProperty(ref _canDataBitrate, value, "CanDataBitrate");
}
private int _canDataSJW = EmbeddedSensors.DATA_SJW_DEFAULT;
public int CanDataSJW
{
get => _canDataSJW;
set => SetProperty(ref _canDataSJW, value, "CanDataSJW");
}
private string _canFileType = EmbeddedSensors.FILETYPE_DEFAULT;
public string CanFileType
{
get => _canFileType;
set => SetProperty(ref _canFileType, value, "CanFileType");
}
public CANRecord(ISensorData sensor)
{
Id = sensor.DatabaseId;
SerialNumber = sensor.SerialNumber;
CanIsFD = sensor.CanIsFD;
CanArbBaseBitrate = sensor.CanArbBaseBitrate;
CanArbBaseSJW = sensor.CanArbBaseSJW;
CanDataBitrate = sensor.CanDataBitrate;
CanDataSJW = sensor.CanDataSJW;
CanFileType = sensor.CanFileType;
Broken = sensor.Broken;
DoNotUse = sensor.DoNotUse;
LastModified = sensor.LastModified;
LastUpdatedBy = sensor.LastUpdatedBy;
}
public CANRecord(IDataReader reader)
{
try
{
Id = Utility.GetInt(reader, "Id");
SerialNumber = Utility.GetString(reader, "SerialNumber");
CanIsFD = Utility.GetBool(reader, "IsFD");
CanArbBaseBitrate = Utility.GetInt(reader, "ArbBaseBitrate");
CanArbBaseSJW = Utility.GetInt(reader, "ArbBaseSJW");
CanDataBitrate = Utility.GetInt(reader, "DataBitrate");
CanDataSJW = Utility.GetInt(reader, "DataSJW");
CanFileType = Utility.GetString(reader, "FileType");
Broken = Utility.GetBool(reader, "Broken");
DoNotUse = Utility.GetBool(reader, "DoNotUse");
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastUpdatedBy = Utility.GetString(reader, "LastModifiedBy");
}
catch (Exception ex)
{
APILogger.Log("Failed to process: ", ex);
}
}
}
}

View File

@@ -0,0 +1,65 @@
using System;
using System.Text;
namespace DTS.Common.Classes.Sensors
{
/// <summary>
/// helper class for the calmode in SIFs which is actually a 3 character sequence for shunt/bridge/filter
/// </summary>
public class CalMode
{
public bool ShuntCheck { get; set; }
public bool FullBridge { get; set; }
public bool Filter { get; set; }
public CalMode(string value)
{
switch (value[0])
{
case 'S':
ShuntCheck = true;
break;
case 'I':
ShuntCheck = false;
break;
default:
throw new NotSupportedException("TDAS::CalMode Invalid calmode position 0: " + value);
}
switch (value[1])
{
case 'D':
FullBridge = true;
break;
case 'S':
FullBridge = false;
break;
default:
throw new NotSupportedException("TDAS::CalMode Invalid calmode position 1: " + value);
}
switch (value[2])
{
case 'F':
Filter = true;
break;
case 'B':
Filter = false;
break;
default:
throw new NotSupportedException("TDAS::CalMode Invalid calmode position 2: " + value);
}
}
public CalMode() { }
public override string ToString()
{
var sb = new StringBuilder();
sb.Append(ShuntCheck ? 'S' : 'I');
sb.Append(FullBridge ? 'D' : 'S');
sb.Append(Filter ? 'F' : 'B');
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,520 @@
using DTS.Common.Interface.Sensors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTS.Common.Enums;
using DTS.Common.Enums.Sensors;
using DTS.Common.Utilities.Logging;
using System.Globalization;
namespace DTS.Common.Classes.Sensors
{
public class CalibrationRecords : ICalibrationRecords
{
public ICalibrationRecord[] Records { get; set; } = new CalibrationRecord[] { new CalibrationRecord() };
public CalibrationRecords(ICalibrationRecords copy)
{
var records = new CalibrationRecord[copy.Records.Length];
for (var i = 0; i < copy.Records.Length; i++)
{
records[i] = new CalibrationRecord(copy.Records[i]);
}
Records = records;
}
public CalibrationRecords()
{
Records = new CalibrationRecord[] { new CalibrationRecord() };
}
public CalibrationRecords(string records)
{
FromSerializedString(records);
}
public bool IsEqual(object obj, ISensorCalibration sc)
{
if (obj is CalibrationRecords r)
{
if (r.Records.Length != Records.Length)
{
return false;
}
for (var i = 0; i < r.Records.Length; i++)
{
if (!r.Records[i].IsEqual(Records[i], sc))
{
return false;
}
}
return true;
}
return base.Equals(obj);
}
public void FromSerializedString(string s)
{
var tokens = s.Split(new string[] { MySeparator }, StringSplitOptions.None);
for (var i = 0; i < tokens.Length; i++)
{
tokens[i] = tokens[i].Replace(MySeparatorBackup, MySeparator);
}
var records = new List<CalibrationRecord>();
foreach (string token in tokens)
{
records.Add(new CalibrationRecord(token));
}
Records = records.ToArray();
}
private const string MySeparator = "__x__";
private const string MySeparatorBackup = "___xx___";
public string ToSerializedString(ISensorCalDbRecord sc)
{
var records = new List<string>();
foreach (var r in Records)
{
records.Add(r.ToSerializedString(sc));
}
for (var i = 0; i < records.Count; i++)
{
System.Diagnostics.Trace.Assert(!records[i].Contains(MySeparatorBackup));
records[i] = records[i].Replace(MySeparator, MySeparatorBackup);
}
return string.Join(MySeparator, records.ToArray());
}
public string ToDisplayString(ISensorCalibration sc, ISensorCalibration previous, string linearFormat, string nonlinearFormat)
{
var sb = new StringBuilder();
for (var i = 0; i < Records.Length; i++)
{
if (i > 0)
{
sb.AppendLine();
}
var r = Records[i];
ICalibrationRecord r2 = null;
if (null != previous)
{
if (i < previous.Records.Records.Length)
{
r2 = previous.Records.Records[i];
}
}
var s = r.ToDisplayString(sc, r2, previous, linearFormat, nonlinearFormat);
if (!string.IsNullOrEmpty(s))
{
sb.Append(s);
}
}
return sb.ToString();
}
}
public class CalibrationRecord : ICalibrationRecord
{
public double Sensitivity { get; set; }
/// <summary>
/// ZeroPoint is used to hold the calibration certificate field for 2D/3D IR-TRACC cal certs
/// it is used to zero the IR-TRACC and POT data prior to being fed into the 3D equations
/// </summary>
private double _zeroPoint = 0D;
public double ZeroPoint
{
get
{
if (false == Equals(Poly.CalibrationFactor, 0.0))
{
// This field is always calculated. Do not return stored value unless we are unable to calculate
return Poly.ZeroPositionIntercept / Poly.CalibrationFactor;
}
return _zeroPoint;
}
set => _zeroPoint = value;
}
public LinearizationFormula Poly { get; set; }
public bool AtCapacity { get; set; } = false;
public string EngineeringUnits { get; set; } = "g";
public SensorConstants.SensUnits SensitivityUnits { get; set; } = SensorConstants.SensUnits.NONE;
public ExcitationVoltageOptions.ExcitationVoltageOption Excitation { get; set; } = ExcitationVoltageOptions.ExcitationVoltageOption.Volt5;
public double CapacityOutputIsBasedOn { get; set; } = 1.000;
public InitialOffsetTypes InitialOffsetMethod { get; set; } = InitialOffsetTypes.EU;
public string ISOCode { get; set; } = String.Empty;
private enum Fields
{
Sensitivity,
Poly,
AtCapacity,
EngineeringUnits,
Excitation,
CapacityOutputIsBasedOn,
SensitivityUnits,
ZeroPoint,
ISOCode
};
public string ToSerializedString(ISensorCalDbRecord parentCal)
{
var tokens = new List<string>();
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
foreach (var field in fields)
{
switch (field)
{
case Fields.AtCapacity:
tokens.Add(AtCapacity.ToString());
break;
case Fields.EngineeringUnits:
tokens.Add(EngineeringUnits);
break;
case Fields.Excitation:
tokens.Add(Excitation.ToString());
break;
case Fields.Poly:
Poly.MarkValid(parentCal.NonLinear);
if (parentCal.LinearAdded)
{
//We have a mixed-sensitivity sensor. Mark the first CR valid, kill the rest
for (var i = 0; i < parentCal.Records.Records.Length; i++)
{
parentCal.Records.Records[i].Poly.MarkValid(i == 0);
}
}
tokens.Add(Poly.ToSerializeString());
break;
case Fields.Sensitivity:
tokens.Add(Sensitivity.ToString(System.Globalization.CultureInfo.InvariantCulture));
break;
case Fields.CapacityOutputIsBasedOn:
tokens.Add(CapacityOutputIsBasedOn.ToString());
break;
case Fields.SensitivityUnits:
tokens.Add(SensitivityUnits.ToString());
break;
case Fields.ZeroPoint:
tokens.Add(ZeroPoint.ToString(System.Globalization.CultureInfo.InvariantCulture));
break;
case Fields.ISOCode:
if (!string.IsNullOrWhiteSpace(ISOCode)) tokens.Add(ISOCode);
break;
default: throw new NotSupportedException("unknown CalibrationRecord field: " + field.ToString());
}
}
for (var i = 0; i < tokens.Count; i++)
{
if (null == tokens[i])
{
tokens[i] = "";
}
tokens[i] = tokens[i].Replace(System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator,
"x_Separator_x");
}
return string.Join(System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator,
tokens.ToArray());
}
public string ToDisplayString(ISensorCalibration sc, ICalibrationRecord previous, ISensorCalibration sc2, string linearFormat, string nonlinearFormat)
{
var sb = new StringBuilder();
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
foreach (var field in fields)
{
switch (field)
{
case Fields.AtCapacity:
if (null == previous || AtCapacity != previous.AtCapacity)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_AtCapacity, AtCapacity);
}
break;
case Fields.EngineeringUnits:
if (null == previous || false == EngineeringUnits.Equals(previous.EngineeringUnits))
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_EngineeringUnits, EngineeringUnits);
}
break;
case Fields.Excitation:
if (null == previous || sc.IsProportional != sc2.IsProportional || Excitation != previous.Excitation)
{
if (sc.IsProportional)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1:0.0}", Strings.Strings.SensorFields_Excitation,
GetExcitationVoltageMagnitudeFromEnum(Excitation));
}
}
break;
case Fields.Poly:
if (null == previous || sc.NonLinear || sc.NonLinear != sc2.NonLinear)
{
if (sc.NonLinear)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_NonLinearFormat,
Poly.ToDisplayString(nonlinearFormat));
}
}
break;
case Fields.Sensitivity:
if (null == previous || Sensitivity != previous.Sensitivity)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_Sensitivity,
Sensitivity.ToString(linearFormat));
}
break;
case Fields.CapacityOutputIsBasedOn:
if (false == AtCapacity)
{
if (null == previous || CapacityOutputIsBasedOn != previous.CapacityOutputIsBasedOn)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_CapacityOutputIsBasedOn,
CapacityOutputIsBasedOn);
}
}
break;
case Fields.SensitivityUnits:
if (null == previous || false == SensitivityUnits.Equals(previous.SensitivityUnits))
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_SensitivityUnits, SensitivityUnits);
}
break;
case Fields.ZeroPoint:
if (null == previous || ZeroPoint != previous.ZeroPoint)
{
if (sb.Length > 1)
{
sb.AppendLine();
}
sb.AppendFormat("{0}: {1}", Strings.Strings.SensorFields_ZeroPoint, ZeroPoint);
}
break;
default:
break;
}
}
return sb.ToString();
}
public bool IsEqual(object obj, ISensorCalibration sc)
{
if (obj is CalibrationRecord r)
{
return r.ToSerializedString(sc) == ToSerializedString(sc);
}
return base.Equals(obj);
}
public void FromString(string s)
{
var tokens = s.Split(new string[] { CultureInfo.InvariantCulture.TextInfo.ListSeparator },
StringSplitOptions.None);
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
for (var i = 0; i < tokens.Length && i < fields.Length; i++)
{
var token = tokens[i].Replace("x_Separator_x",
CultureInfo.InvariantCulture.TextInfo.ListSeparator);
switch (fields[i])
{
case Fields.AtCapacity:
AtCapacity = Convert.ToBoolean(token);
break;
case Fields.EngineeringUnits:
EngineeringUnits = token;
break;
case Fields.Excitation:
if (Enum.TryParse(token, out ExcitationVoltageOptions.ExcitationVoltageOption excitation))
{
Excitation = excitation;
}
else { APILogger.Log($"failed to parse excitation: {token} from {s}"); }
break;
case Fields.Poly:
Poly = new LinearizationFormula();
Poly.FromSerializeString(token);
break;
case Fields.Sensitivity:
Sensitivity = Convert.ToDouble(token, System.Globalization.CultureInfo.InvariantCulture);
break;
case Fields.CapacityOutputIsBasedOn:
CapacityOutputIsBasedOn = Convert.ToDouble(token);
break;
case Fields.SensitivityUnits:
if (Enum.TryParse(token, out SensorConstants.SensUnits unit))
{
SensitivityUnits = unit;
}
else { APILogger.Log($"failed to parse sensitivity units: {token} from {s}"); }
break;
case Fields.ZeroPoint:
ZeroPoint = Convert.ToDouble(token, System.Globalization.CultureInfo.InvariantCulture);
break;
case Fields.ISOCode:
ISOCode = token;
break;
default: throw new NotSupportedException("unknown CalibrationRecord field: " + fields.ToArray());
}
}
}
public CalibrationRecord(string s)
{
FromString(s);
}
public CalibrationRecord(ICalibrationRecord copy)
{
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
foreach (var field in fields)
{
switch (field)
{
case Fields.AtCapacity:
AtCapacity = copy.AtCapacity;
break;
case Fields.EngineeringUnits:
EngineeringUnits = copy.EngineeringUnits;
break;
case Fields.Excitation:
Excitation = copy.Excitation;
break;
case Fields.Poly:
Poly = new LinearizationFormula(copy.Poly);
break;
case Fields.Sensitivity:
Sensitivity = copy.Sensitivity;
break;
case Fields.CapacityOutputIsBasedOn:
CapacityOutputIsBasedOn = copy.CapacityOutputIsBasedOn;
break;
case Fields.SensitivityUnits:
SensitivityUnits = copy.SensitivityUnits;
break;
case Fields.ZeroPoint:
ZeroPoint = copy.ZeroPoint;
break;
case Fields.ISOCode:
ISOCode = copy.ISOCode;
break;
default:
throw new NotSupportedException("unknown calibrationrecord field: " + field.ToString());
}
}
}
public CalibrationRecord()
{
Poly = new LinearizationFormula();
}
//helpers moved from DAS.Concepts
public static double GetExcitationVoltageMagnitudeFromEnum(ExcitationVoltageOptions.ExcitationVoltageOption target)
{
try
{
return new ExcitationVoltageOptions.VoltageMagnitudeAttributeCoder().DecodeAttributeValue(target);
}
catch (Exception ex)
{
throw new Exception("encountered problem attempting to get excitation voltage magnitude from enum", ex);
}
}
public static ExcitationVoltageOptions.ExcitationVoltageOption GetExcitationVoltageEnumFromMagnitude(double magnitude)
{
try
{
return new ExcitationVoltageOptions.VoltageMagnitudeAttributeCoder().EncodeAttributeValue(magnitude);
}
catch (Exception ex)
{
APILogger.Log("encountered problem attempting to get excitation voltage enum from magnitude", ex);
return ExcitationVoltageOptions.ExcitationVoltageOption.Undefined;
}
}
}
}

View File

@@ -0,0 +1,23 @@
using DTS.Common.Enums.Sensors;
namespace DTS.Common.Classes.Sensors
{
public static class ChannelSerialNumber
{
public static string SerialNumberFromChannel(bool isTestSpecificEmbedded, string testSpecificEmbeddedSensor, string sensorDataSerialNumber)
{
var serialNumber = string.Empty;
if (isTestSpecificEmbedded)
{
serialNumber = testSpecificEmbeddedSensor;
}
else
{
serialNumber = sensorDataSerialNumber;
}
return serialNumber;
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Linq;
namespace DTS.Common.Classes.Sensors
{
public enum KnownChannelTypes
{
VS,
VU,
SB,
TI,
TC,
CT,
XP,
P4,
VF,
NB,
EX,
X1,
R1,
VO,
CO,
CP
}
public static class ChannelTypeUtility
{
//FB 44299
public static string ParseSensorKnownChannelType(string sensorName)
{
if (string.IsNullOrEmpty(sensorName)) return string.Empty;
if (sensorName.Length < 2) return string.Empty;
var parsedCode = sensorName.Substring(0, 2).ToUpper();
var knownsCodes = Enum.GetValues(typeof(KnownChannelTypes)).Cast<KnownChannelTypes>().Select(x => x.ToString()).ToArray();
if (knownsCodes.Contains(parsedCode)) return parsedCode;
return string.Empty;
}
}
}

View File

@@ -0,0 +1,320 @@
using DTS.Common.Base;
using DTS.Common.Enums;
using DTS.Common.Interface.Sensors;
using DTS.Common.Interface.Sensors.SoftwareFilters;
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Linq;
namespace DTS.Common.Classes.Sensors
{
/// <summary>
/// Implementation of IDigitalInDbRecord
/// represents a record of a digital input setting in the database
/// <inheritdoc cref="IDigitalInDbRecord"/>
/// </summary>
public class DigitalInDbRecord : BasePropertyChanged, IDigitalInDbRecord
{
private int _id = -1;
/// <summary>
/// Database id of record
/// </summary>
[Key]
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private string _serialNumber = "";
/// <summary>
/// serial number or name of setting
/// </summary>
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
private DigitalInputModes _settingMode = DigitalInputModes.TLH;
/// <summary>
/// Input mode for setting
/// </summary>
public DigitalInputModes Mode
{
get => _settingMode;
set => SetProperty(ref _settingMode, value, "Mode");
}
private IDigitalInputScaleMultiplier _scaleMultiplier = new DigitalInputScaleMultiplier();
/// <summary>
/// ScaleMultiplier, defines how to interpret output in terms of
/// units or active/default value of input state
/// </summary>
[Required]
[StringLength(50)]
public IDigitalInputScaleMultiplier ScaleMultiplier
{
get => _scaleMultiplier;
set => SetProperty(ref _scaleMultiplier, value, "ScaleMultiplier");
}
private DateTime _lastModified = DateTime.MinValue;
[Column(TypeName = "datetime")]
/// <summary>
/// when setting was last modified
/// </summary>
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private string _lastModifiedBy = "";
/// <summary>
/// user that last modified setting in db
/// </summary>
[Required]
[StringLength(50)]
public string LastModifiedBy
{
get => _lastModifiedBy;
set => SetProperty(ref _lastModifiedBy, value, "LastModifiedBy");
}
private string _eId = "";
/// <summary>
/// Electronic ID for digital input setting
/// (dallas or TeDS ID value)
/// </summary>
[Required]
[Column("eId")]
[StringLength(50)]
public string EID
{
get => _eId;
set => SetProperty(ref _eId, value, "EID");
}
private string _isoCode = "";
/// <summary>
/// ISO 13499 code for digital input data collected using this setting
/// this is the default code when the setting is applied to an input channel
/// but can be changed in group or test settings
/// </summary>
[Required]
[StringLength(50)]
public string ISOCode
{
get => _isoCode;
set => SetProperty(ref _isoCode, value, "ISOCode");
}
private string _isoChannelName = "";
/// <summary>
/// the associated ISO 13499 channel name to apply to a channel when applying
/// setting to an input channel
/// but can be changed in group or test settings
/// </summary>
[Required]
[StringLength(255)]
public string ISOChannelName
{
get => _isoChannelName;
set => SetProperty(ref _isoChannelName, value, "ISOChannelName");
}
private string _userCode = "";
/// <summary>
/// the user code to apply to a channel when applying setting to a channel
/// can be changed in group or test settings
/// </summary>
[Required]
[StringLength(50)]
public string UserCode
{
get => _userCode;
set => SetProperty(ref _userCode, value, "UserCode");
}
private string _userChannelName = "";
/// <summary>
/// user channel name to apply to a channel when applying setting to a channel
/// can be changed in group or test settings
/// </summary>
[Required]
[StringLength(255)]
public string UserChannelName
{
get => _userChannelName;
set => SetProperty(ref _userChannelName, value, "UserChannelName");
}
private string _userValue1 = "";
/// <summary>
/// user value to carry through to collected data channel when collecting data with this setting
/// </summary>
[StringLength(255)]
public string UserValue1
{
get => _userValue1;
set => SetProperty(ref _userValue1, value, "UserValue1");
}
private string _userValue2 = "";
/// <summary>
/// user value to carry through to collected data channel when collecting data with this setting
/// </summary>
[StringLength(255)]
public string UserValue2
{
get => _userValue2;
set => SetProperty(ref _userValue2, value, "UserValue2");
}
private string _userValue3 = "";
/// <summary>
/// user value to carry through to collected data channel when collecting data with this setting
/// </summary>
[StringLength(255)]
public string UserValue3
{
get => _userValue3;
set => SetProperty(ref _userValue3, value, "UserValue3");
}
private byte[] _userTags;
/// <summary>
/// bytes describing tag ids for tags associated with setting
/// see ITagAware for more information
/// </summary>
public byte[] UserTags
{
get => _userTags;
set => SetProperty(ref _userTags, value, "UserTags");
}
private string _measurementUnit = "V";
/// <summary>
/// measurement unit for collected data, for example
/// 'V' or Volts
/// </summary>
[Required]
[StringLength(50)]
public string MeasurementUnit
{
get => _measurementUnit;
set => SetProperty(ref _measurementUnit, value, "MeasurementUnit");
}
private IFilterClass _filterClass;
/// <summary>
/// software filter class (applied when viewing data) to apply to collected data by default
/// can be changed when viewing or exporting, this is just a default filter
/// </summary>
[Required]
[StringLength(50)]
public IFilterClass FilterClass
{
get => _filterClass;
set => SetProperty(ref _filterClass, value, "FilterClass");
}
private bool _doNotUse = false;
/// <summary>
/// a flag indicating setting should not be used for arbitrary user specified reason
/// </summary>
public bool DoNotUse
{
get => _doNotUse;
set => SetProperty(ref _doNotUse, value, "DoNotUse");
}
private bool _broken = false;
/// <summary>
/// a flag indicating setting should not be used because it is currently broken
/// </summary>
public bool Broken
{
get => _broken;
set => SetProperty(ref _broken, value, "Broken");
}
public DigitalInDbRecord() { }
public DigitalInDbRecord(ISensorData copy, byte[] tagBlockBytes, IDigitalInputScaleMultiplier digitalScaleMultiplier)
{
Id = copy.DatabaseId;
SerialNumber = copy.SerialNumber;
ISOCode = copy.ISOCode;
ISOChannelName = copy.ISOChannelName;
UserCode = copy.UserCode;
UserChannelName = copy.UserChannelName;
Broken = copy.Broken;
DoNotUse = copy.DoNotUse;
LastModified = copy.LastModified;
LastModifiedBy = copy.LastUpdatedBy;
Mode = copy.InputMode;
MeasurementUnit = copy.DIUnits;
FilterClass = new FilterClass(copy.FilterClass.FClass, copy.FilterClass.Frequency);
ISOCode = copy.ISOCode;
EID = copy.EID;
UserValue1 = copy.UserValue1;
UserValue2 = copy.UserValue2;
UserValue3 = copy.UserValue3;
if (null == tagBlockBytes) { UserTags = null; }
else
{
if (tagBlockBytes.Any())
{
UserTags = new byte[tagBlockBytes.Length];
Array.Copy(tagBlockBytes, UserTags, tagBlockBytes.Length);
}
else { UserTags = new byte[0]; }
}
ScaleMultiplier.FromDbSerializeString(digitalScaleMultiplier.ToSerializeDbString());
}
public DigitalInDbRecord(IDataReader reader)
{
Id = Utility.GetInt(reader, "Id", -1);
SerialNumber = Utility.GetString(reader, "SerialNumber", string.Empty);
ISOCode = Utility.GetString(reader, "ISOCode", string.Empty);
ISOChannelName = Utility.GetString(reader, "ISOChannelName", string.Empty);
UserCode = Utility.GetString(reader, "UserCode", string.Empty);
UserChannelName = Utility.GetString(reader, "UserChannelName", string.Empty);
Broken = Utility.GetBool(reader, "Broken", false);
DoNotUse = Utility.GetBool(reader, "DoNotUse", false);
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastModifiedBy = Utility.GetString(reader, "LastModifiedBy", string.Empty);
Mode = (DigitalInputModes)Utility.GetInt(reader, "SettingMode");
MeasurementUnit = Utility.GetString(reader, "MeasurementUnit");
FilterClass = new FilterClass(Utility.GetString(reader, "FilterClass"));
if (ISOCode.Length < 16) { ISOCode = ISOCode.PadRight(16, '?'); }
var s = ISOCode.ToCharArray();
s[15] = '0';
ISOCode = new string(s);
EID = Utility.GetString(reader, "eId", string.Empty);
UserValue1 = Utility.GetString(reader, "UserValue1", string.Empty);
UserValue2 = Utility.GetString(reader, "UserValue2", string.Empty);
UserValue3 = Utility.GetString(reader, "UserValue3", string.Empty);
UserTags = (byte[])reader["UserTags"];
ScaleMultiplier.FromDbSerializeString(Utility.GetString(reader, "ScaleMultiplier"));
}
public DigitalInDbRecord(IDigitalInDbRecord copy)
{
Id = copy.Id;
SerialNumber = copy.SerialNumber;
ISOCode = copy.ISOCode;
ISOChannelName = copy.ISOChannelName;
UserCode = copy.UserCode;
UserChannelName = copy.UserChannelName;
Broken = copy.Broken;
DoNotUse = copy.DoNotUse;
LastModified = copy.LastModified;
LastModifiedBy = copy.LastModifiedBy;
Mode = copy.Mode;
MeasurementUnit = copy.MeasurementUnit;
FilterClass = new FilterClass(copy.FilterClass.FClass, copy.FilterClass.Frequency);
ISOCode = copy.ISOCode;
EID = copy.EID;
UserValue1 = copy.UserValue1;
UserValue2 = copy.UserValue2;
UserValue3 = copy.UserValue3;
if (null == copy.UserTags) { UserTags = null; }
else
{
if (copy.UserTags.Any())
{
var userTags = new byte[copy.UserTags.Length];
Array.Copy(copy.UserTags, userTags, copy.UserTags.Length);
UserTags = userTags;
}
else { UserTags = new byte[0]; }
}
ScaleMultiplier.FromDbSerializeString(copy.ScaleMultiplier.ToSerializeDbString());
}
}
}

View File

@@ -0,0 +1,131 @@
using DTS.Common.Interface.Sensors;
using System;
namespace DTS.Common.Classes.Sensors
{
/// <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>
public class DigitalInputScaleMultiplier : IDigitalInputScaleMultiplier
{
public Forms Form { get; set; } = Forms.ArbitraryLowAndHigh;
/// <summary>
/// for arbirary low/high, this is the low value, the value 0 should be displayed as (OFF)
/// </summary>
public double DefaultValue { get; set; }
/// <summary>
/// for arbitrary low/high, this is the high value, the value 1 should be displayed as (ON)
/// </summary>
public double ActiveValue { get; set; } = 1D;
public bool SimpleEquals(IDigitalInputScaleMultiplier rhs)
{
return Form == rhs.Form && DefaultValue == rhs.DefaultValue && ActiveValue == rhs.ActiveValue;
}
public override bool Equals(object obj)
{
if (obj is DigitalInputScaleMultiplier)
{
var b = obj as DigitalInputScaleMultiplier;
return b.Form == Form
&& b.ActiveValue == ActiveValue
&& b.DefaultValue == DefaultValue;
}
else { return false; }
}
public override int GetHashCode()
{
//the idea here is to use two primes to avoid collisions, it's not perfect but should work in general and we can predict when it won't
if (ActiveValue == 31 || DefaultValue == 31 || DefaultValue == 79 || ActiveValue == 79)
{
return (int)Form + Convert.ToInt32(ActiveValue * 127) + Convert.ToInt32(DefaultValue * 23);
}
else
{
return (int)Form + Convert.ToInt32(ActiveValue * 31) + Convert.ToInt32(DefaultValue * 79);
}
}
/// <summary>
/// constructor and copy constructor
/// </summary>
public DigitalInputScaleMultiplier()
{
DefaultValue = 0D;
}
public DigitalInputScaleMultiplier(DigitalInputScaleMultiplier copy)
{
Form = copy.Form;
DefaultValue = copy.DefaultValue;
ActiveValue = copy.ActiveValue;
}
/// <summary>
/// serializes scaler to a string
/// </summary>
/// <returns></returns>
public string ToSerializeDbString()
{
switch (Form)
{
case Forms.ArbitraryLowAndHigh: return ToSerializeDbStringLowAndHigh();
default: throw new NotSupportedException("DigitalScaleMultiplier::ToSerializeDbString unsupported form: " + Form);
}
}
/// <summary>
/// serializes an ArbitraryLowHigh to a string
/// </summary>
/// <returns></returns>
private string ToSerializeDbStringLowAndHigh() { return string.Format("{1}{0}{2}{0}{3}", System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator, Form, DefaultValue.ToString(System.Globalization.CultureInfo.InvariantCulture), ActiveValue.ToString(System.Globalization.CultureInfo.InvariantCulture)); }
/// <summary>
/// deserializes an arbitrary low/high from a string
/// </summary>
/// <param name="tokens"></param>
private void FromDbSerializeStringLowAndHigh(string[] tokens)
{
if (tokens.Length < 3) { throw new NotSupportedException("DigitalInputScaleMultiplier::FromDbSerializeStringLowAndHigh invalid format for scale multiplier"); }
if (double.TryParse(tokens[1], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out double d))
{
DefaultValue = d;
}
else { throw new NotSupportedException("DigitalInputScaleMultiplier::FromDbSerializeStringLowAndHigh invalid format for low value: " + tokens[1]); }
if (double.TryParse(tokens[2], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out d))
{
ActiveValue = d;
}
else { throw new NotSupportedException("DigitalInputScaleMultiplier::FromDbSerializeStringLowAndHigh invalid format for high value: " + tokens[2]); }
}
/// <summary>
/// deserializes a scaler from a string, regardless of format
/// </summary>
/// <param name="s"></param>
public void FromDbSerializeString(string s)
{
if (null == s)
{
Utilities.Logging.APILogger.Log("Unable to serialize Db. String is null.");
//FIXME is this the right thing to do?
return;
//throw new NotSupportedException("DigitalINputScaleMultiplier::FromDbSerializeString nothing to parse");
}
var tokens = s.Split(new[] { System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator }, StringSplitOptions.None);
if (Enum.TryParse(tokens[0], out Forms form))
{
Form = form;
switch (form)
{
case Forms.ArbitraryLowAndHigh: FromDbSerializeStringLowAndHigh(tokens); break;
default: throw new NotSupportedException("DigitalInputScaleMultiplier::FromDbSerializeString unsupported form " + form);
}
}
else { throw new NotSupportedException("DigitalINputScaleMultiplier::FromDbSerializeString unsupported format: " + s); }
}
}
}

View File

@@ -0,0 +1,180 @@
using DTS.Common.Base;
using DTS.Common.Enums;
using DTS.Common.Interface.Sensors;
using System;
using System.Data;
using System.Linq;
namespace DTS.Common.Classes.Sensors
{
public class DigitalOutDbRecord : BasePropertyChanged, IDigitalOutDbRecord
{
private string _serialNumber = "";
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
private double _doDelay = 0D;
public double DODelay
{
get => _doDelay;
set => SetProperty(ref _doDelay, value, "DODelay");
}
private double _doDuration = 0D;
public double DODuration
{
get => _doDuration;
set => SetProperty(ref _doDuration, value, "DODuration");
}
private string _modifiedBy = "";
public string ModifiedBy
{
get => _modifiedBy;
set => SetProperty(ref _modifiedBy, value, "ModifiedBy");
}
private DateTime _lastModified = DateTime.MinValue;
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private int _databaseId = -1;
public int DatabaseId
{
get => _databaseId;
set => SetProperty(ref _databaseId, value, "DatabaseId");
}
private string _isoCode = "";
public string ISOCode
{
get => _isoCode;
set => SetProperty(ref _isoCode, value, "ISOCode");
}
private string _isoChannelName = "";
public string ISOChannelName
{
get => _isoChannelName;
set => SetProperty(ref _isoChannelName, value, "ISOChannelName");
}
private string _userCode = "";
public string UserCode
{
get => _userCode;
set => SetProperty(ref _userCode, value, "UserCode");
}
private string _userChannelName = "";
public string UserChannelName
{
get => _userChannelName;
set => SetProperty(ref _userChannelName, value, "UserChannelName");
}
private bool _broken = false;
public bool Broken
{
get => _broken;
set => SetProperty(ref _broken, value, "Broken");
}
private bool _doNotUse = false;
public bool DoNotUse
{
get => _doNotUse;
set => SetProperty(ref _doNotUse, value, "DoNotUse");
}
private DigitalOutputModes _doMode = DigitalOutputModes.CCNC;
public DigitalOutputModes DOMode
{
get => _doMode;
set => SetProperty(ref _doMode, value, "DOMode");
}
private bool _limitDuration = true;
public bool LimitDuration
{
get => _limitDuration;
set => SetProperty(ref _limitDuration, value, "LimitDuration");
}
private int _version = 0;
public int Version
{
get => _version;
set => SetProperty(ref _version, value, "Version");
}
private byte[] _tagsBlobBytes = null;
public byte[] TagsBlobBytes
{
get => _tagsBlobBytes;
set => SetProperty(ref _tagsBlobBytes, value, "TagsBlobBytes");
}
public DigitalOutDbRecord()
{
}
public DigitalOutDbRecord(ISensorData copy, byte[] tagsBlobBytes)
{
SerialNumber = copy.SerialNumber;
DatabaseId = copy.DatabaseId;
Broken = copy.Broken;
DoNotUse = copy.DoNotUse;
Version = copy.Version;
DOMode = copy.DigitalOutputMode;
LimitDuration = copy.DigitalOutputLimitDuration;
ModifiedBy = copy.LastUpdatedBy;
LastModified = copy.LastModified;
DODuration = copy.DigitalOutputDurationMS;
DODelay = copy.DigitalOutputDelayMS;
if (null == tagsBlobBytes)
{
TagsBlobBytes = null;
}
else if (tagsBlobBytes.Any())
{
var bytes = new byte[tagsBlobBytes.Length];
Array.Copy(tagsBlobBytes, bytes, tagsBlobBytes.Length);
TagsBlobBytes = bytes;
}
else { TagsBlobBytes = new byte[0]; }
}
public DigitalOutDbRecord(IDigitalOutDbRecord copy)
{
SerialNumber = copy.SerialNumber;
DatabaseId = copy.DatabaseId;
Broken = copy.Broken;
DoNotUse = copy.DoNotUse;
Version = copy.Version;
DOMode = copy.DOMode;
LimitDuration = copy.LimitDuration;
ModifiedBy = copy.ModifiedBy;
LastModified = copy.LastModified;
DODuration = copy.DODuration;
DODelay = copy.DODelay;
if (null == copy.TagsBlobBytes)
{
TagsBlobBytes = null;
}
else if (copy.TagsBlobBytes.Any())
{
var tagsBlobBytes = new byte[copy.TagsBlobBytes.Length];
Array.Copy(copy.TagsBlobBytes, tagsBlobBytes, copy.TagsBlobBytes.Length);
TagsBlobBytes = tagsBlobBytes;
}
else { TagsBlobBytes = new byte[0]; }
}
public DigitalOutDbRecord(IDataReader reader)
{
DatabaseId = Utility.GetInt(reader, "Id", -1);
Broken = Utility.GetBool(reader, "Broken", false);
DoNotUse = Utility.GetBool(reader, "DoNotUse");
SerialNumber = Utility.GetString(reader, "SerialNumber");
Version = Utility.GetInt(reader, "Version");
DOMode = (DigitalOutputModes)Utility.GetInt(reader, "OutputMode");
LimitDuration = Utility.GetBool(reader, "LimitDuration", true);
ModifiedBy = Utility.GetString(reader, "LastModifiedBy", string.Empty);
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
DODuration = Utility.GetDouble(reader, "DurationMSFloat");
DODelay = Utility.GetDouble(reader, "DelayMS");
TagsBlobBytes = (byte[])reader["UserTags"];
}
}
}

View File

@@ -0,0 +1,13 @@
namespace DTS.Common.Classes.Sensors
{
public class DisplayedCalibrationBehavior
{
public DTS.Common.Enums.Sensors.CalibrationBehaviors CalibrationBehavior;
public string DisplayString;
public override string ToString()
{
return DisplayString;
}
}
}

View File

@@ -0,0 +1,634 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.ComponentModel;
using System.Globalization;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.Sensors.SoftwareFilters;
using DTS.Common.Interface.Sensors;
using System.Linq;
namespace DTS.Common.Classes.Sensors
{
[ReadOnly(true)]
public class FilterClass : INotifyPropertyChanged, IFilterClass
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, String propertyName = null)
{
if (Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
[ReadOnly(true)]
public FilterClassType FClass { get; set; }
//FB 13120 used for filter options drop down localization
public string FilterName
{
get
{
string name = "";
if (FClass == FilterClassType.None)
{
name = Strings.Strings.FilterClassType_None;
}
else if (FClass == FilterClassType.Unfiltered)
{
name = Strings.Strings.FilterClassType_Unfiltered;
}
else if (FClass == FilterClassType.AdHoc)
{
name = Frequency.ToString();
}
else
{
name = Frequency + " (" + FClass.ToString() + ")";
}
return name;
}
}
/// <summary>
/// Gets the numeric filter class value for the filter class; EX CFC60 returns 60, CFC1000 returns 1000
/// </summary>
/// <returns>integer for filter class name</returns>
public int GetFilterClassNumericValue()
{
switch (FClass)
{
case FilterClassType.CFC10:
return 10;
case FilterClassType.CFC60:
return 60;
case FilterClassType.CFC180:
return 180;
case FilterClassType.CFC600:
return 600;
case FilterClassType.None:
return 0;
case FilterClassType.Unfiltered:
return -2;
default: // adhoc and cfc1000 enter here
return 1000;
}
}
private double _Frequency;
[ReadOnly(true)]
public double Frequency
{
get { return _Frequency; }
set { _Frequency = value; }
}
#region Tags
internal const string FilterClassTag = "FilterClass";
internal const string ClassTag = "Class";
internal const string FrequencyTag = "Frequency";
#endregion
private string TableName;
public FilterClass(XElement elem, string prefix, string tblName, string id)
{
TableName = tblName;
XElement inner = null;
try
{
inner = elem.Element(mkTag(prefix));
}
catch (ArgumentNullException)
{
if (!string.IsNullOrEmpty(id))
{
throw new System.Exception(string.Format("{0}: Can't find tag {1} for entry {2}", TableName, prefix + "-" + FilterClassTag, id));
}
throw new System.Exception(string.Format("{0}: Can't find tag {1} in file", TableName, prefix + "-" + FilterClassTag));
}
FClass = (FilterClassType)Enum.Parse(typeof(FilterClassType), inner.Attribute(ClassTag).Value);
switch (FClass)
{
case FilterClassType.None:
_Frequency = (double)FilterClassType.None;
break;
case FilterClassType.Unfiltered:
_Frequency = (double)FilterClassType.Unfiltered;
break;
case FilterClassType.CFC10:
_Frequency = (double)FilterClassType.CFC10;
break;
case FilterClassType.CFC60:
_Frequency = (double)FilterClassType.CFC60;
break;
case FilterClassType.CFC180:
_Frequency = (double)FilterClassType.CFC180;
break;
case FilterClassType.CFC600:
_Frequency = (double)FilterClassType.CFC600;
break;
case FilterClassType.CFC1000:
_Frequency = (double)FilterClassType.CFC1000;
break;
case FilterClassType.AdHoc:
if (!double.TryParse(inner.Value, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out _Frequency))
{
throw new System.Exception(string.Format("{0}: Invalid filter frequency {1}", TableName, inner.Value));
}
break;
}
}
public FilterClass(FilterClassType fc, double freq)
{
FClass = fc;
Frequency = freq;
}
public static FilterClassType GetFilterClassTypeFromNumericFC(int fc)
{
switch (fc)
{
case 1000:
case -1:
return FilterClassType.CFC1000;
case 600:
return FilterClassType.CFC600;
case 180:
return FilterClassType.CFC180;
case 60:
return FilterClassType.CFC60;
case 10:
return FilterClassType.CFC10;
case 0:
return FilterClassType.None;
case -2:
return FilterClassType.Unfiltered;
default:
return FilterClassType.None;
}
}
public FilterClass(double freq)
{
Frequency = freq;
if (freq == (double)FilterClassType.CFC10)
{
FClass = FilterClassType.CFC10;
}
else if (freq == (double)FilterClassType.CFC60)
{
FClass = FilterClassType.CFC60;
}
else if (freq == (double)FilterClassType.CFC180)
{
FClass = FilterClassType.CFC180;
}
else if (freq == (double)FilterClassType.CFC600)
{
FClass = FilterClassType.CFC600;
}
else if (freq == (double)FilterClassType.CFC1000)
{
FClass = FilterClassType.CFC1000;
}
else if (freq == 0)
{
FClass = FilterClassType.None;
}
else if (freq == (double)FilterClassType.Unfiltered)
{
FClass = FilterClassType.Unfiltered;
}
else
{
FClass = FilterClassType.AdHoc;
//FB 13120 set the frequency for ad hoc filters
Frequency = freq;
}
}
/// <summary>
///FB 13120 Specify and return the default filter class
/// </summary>
/// <returns></returns>
public static FilterClass GetDefaultFilterClass(List<ISoftwareFilter> softwareFilters)
{
if (softwareFilters == null)
{
return new FilterClass(FilterClassType.CFC1000);
}
var softwareFilter = softwareFilters.Find(p => p.IsDefault);
FilterClass fc = null;
switch (softwareFilter?.ISOCode)
{
case '0':
fc = new FilterClass(FilterClassType.Unfiltered);
break;
case 'P':
fc = new FilterClass(FilterClassType.None);
break;
case 'S':
fc = new FilterClass(FilterClassType.AdHoc, softwareFilter.Frequency);
break;
case 'A':
fc = new FilterClass(FilterClassType.CFC1000);
break;
case 'B':
fc = new FilterClass(FilterClassType.CFC600);
break;
case 'C':
fc = new FilterClass(FilterClassType.CFC180);
break;
case 'D':
fc = new FilterClass(FilterClassType.CFC60);
break;
default:
fc = new FilterClass(FilterClassType.CFC1000);
break;
}
return fc;
}
/// <summary>
/// FB 13120 Get the filter class based on the isoCode provided
/// </summary>
/// <param name="isoCode"></param>
/// <param name="frequency">this frequency will be used for AdHoc filter</param>
/// <returns></returns>
public static FilterClass GetFilterClassFromIsoCode(string isoCode, double frequency = 0)
{
if (string.IsNullOrEmpty(isoCode))
{
return new FilterClass(FilterClassType.CFC1000);
}
FilterClass fc = null;
switch (isoCode.ToUpper())
{
case "0":
fc = new FilterClass(FilterClassType.Unfiltered);
break;
case "P":
fc = new FilterClass(FilterClassType.None);
break;
case "S":
fc = new FilterClass(FilterClassType.AdHoc, frequency);
break;
case "A":
fc = new FilterClass(FilterClassType.CFC1000);
break;
case "B":
fc = new FilterClass(FilterClassType.CFC600);
break;
case "C":
fc = new FilterClass(FilterClassType.CFC180);
break;
case "D":
fc = new FilterClass(FilterClassType.CFC60);
break;
default:
fc = new FilterClass(FilterClassType.CFC1000);
break;
}
return fc;
}
/// <summary>
/// FB 15574 Get the FilterClass setting from cfc iso code
/// </summary>
/// <param name="cfcIsoCode">cfc iso code ex: A</param>
/// <returns>filter class setting on format of FilterType,Frequency ex: None,0 </returns>
public static string GetFilterClassSettingFromCFC(string cfcIsoCode)
{
var filterClass = GetFilterClassFromIsoCode(cfcIsoCode);
return $"{filterClass.FClass.ToString()},{filterClass.Frequency}";
}
/// <summary>
///FB 15574 Get the FilterClass setting from FilterClass
/// </summary>
/// <param name="filterClass"></param>
/// <returns>filter class setting on format of FilterType,Frequency ex: None,0 </returns>
public static string GetFilterClassSettingFromFilterClass(IFilterClass filterClass)
{
return $"{filterClass.FClass.ToString()},{filterClass.Frequency}";
}
public static double GetFrequencyFromFilterClassType(FilterClassType filterClassType)
{
if (filterClassType == FilterClassType.AdHoc)
{
throw new Exception("GetFrequencyFromFilterClassType: AdHoc FilterClassType does not have frequency associated");
}
return (double)filterClassType;
}
public static FilterClass GetFilterClassFromFilterClassType(FilterClassType filterClassType, double adHocFrequency = 0)
{
if (filterClassType == FilterClassType.AdHoc)
{
return new FilterClass(filterClassType, adHocFrequency);
}
return new FilterClass(filterClassType);
}
public static FilterClass GetFilterClassFromFilterClassSetting(string filterClassSetting)
{
if (string.IsNullOrEmpty(filterClassSetting))
{
return GetFilterClassFromFilterClassType(FilterClassType.Unfiltered);
}
var setting = filterClassSetting.Split(',');
if (Enum.TryParse(setting[0], out FilterClassType fct))
{
return GetFilterClassFromFilterClassType(fct, Convert.ToDouble(setting[1]));
}
return GetFilterClassFromFilterClassType(FilterClassType.Unfiltered);
}
public FilterClass(FilterClassType fc)
{
FClass = fc;
switch (fc)
{
case FilterClassType.None:
Frequency = 0;
break;
case FilterClassType.AdHoc:
Frequency = (double)FilterClassType.AdHoc;
break;
case FilterClassType.Unfiltered:
Frequency = (double)FilterClassType.Unfiltered;
break;
case FilterClassType.CFC10:
Frequency = (double)FilterClassType.CFC10;
break;
case FilterClassType.CFC60:
Frequency = (double)FilterClassType.CFC60;
break;
case FilterClassType.CFC180:
Frequency = (double)FilterClassType.CFC180;
break;
case FilterClassType.CFC600:
Frequency = (double)FilterClassType.CFC600;
break;
case FilterClassType.CFC1000:
Frequency = (double)FilterClassType.CFC1000;
break;
default:
throw new System.Exception("FilterClass: unknown class");
}
}
public XElement ToXElement(string prefix)
{
var element = new XElement(mkTag(prefix), Frequency);
element.SetAttributeValue(ClassTag, FClass.ToString());
return element;
}
public void Update(XElement elem, string prefix)
{
elem.SetElementValue(mkTag(prefix), Frequency);
var element = elem.Element(mkTag(prefix));
element.SetAttributeValue(ClassTag, FClass.ToString());
}
public static string mkTag(string prefix)
{
return prefix + "-" + FilterClassTag;
}
public override string ToString()
{
switch (FClass)
{
case FilterClassType.None:
return "None";
case FilterClassType.Unfiltered:
return "Unfiltered";
case FilterClassType.CFC10:
return string.Format("{0} (CFC10)", (int)FilterClassType.CFC10);
case FilterClassType.CFC60:
return string.Format("{0} (CFC60)", (int)FilterClassType.CFC60);
case FilterClassType.CFC180:
return string.Format("{0} (CFC180)", (int)FilterClassType.CFC180);
case FilterClassType.CFC600:
return string.Format("{0} (CFC600)", (int)FilterClassType.CFC600);
case FilterClassType.CFC1000:
return string.Format("{0} (CFC1000)", (int)FilterClassType.CFC1000);
case FilterClassType.AdHoc:
return ((int)Frequency).ToString();
}
throw new System.Exception("FilterClass.ToString: Invalid class=" + FClass.ToString());
}
public FilterClass(string fclass)
{
int fc;
if (int.TryParse(fclass, NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out fc))
{
switch (fc)
{
case 17:
FClass = FilterClassType.CFC10;
_Frequency = (double)FClass;
return;
case 100:
FClass = FilterClassType.CFC60;
_Frequency = (double)FClass;
return;
case 300:
FClass = FilterClassType.CFC180;
_Frequency = (double)FClass;
return;
case 1000:
FClass = FilterClassType.CFC600;
_Frequency = (double)FClass;
return;
case 1650:
FClass = FilterClassType.CFC1000;
_Frequency = (double)FClass;
return;
}
}
if (string.IsNullOrEmpty(fclass) || fclass == "None")
{
FClass = FilterClassType.None;
}
else if (fclass.Contains("Unfiltered"))
{
FClass = FilterClassType.Unfiltered;
_Frequency = (double)FilterClassType.Unfiltered;
}
else if (fclass.Contains("CFC1000"))
{
FClass = FilterClassType.CFC1000;
_Frequency = (double)FilterClassType.CFC1000;
}
else if (fclass.Contains("CFC600"))
{
FClass = FilterClassType.CFC600;
_Frequency = (double)FilterClassType.CFC600;
}
else if (fclass.Contains("CFC60"))
{
FClass = FilterClassType.CFC60;
_Frequency = (double)FilterClassType.CFC60;
}
else if (fclass.Contains("CFC180"))
{
FClass = FilterClassType.CFC180;
_Frequency = (double)FilterClassType.CFC180;
}
else
{
//FB 13120 parse and set frequncy
double freq = 0;
if (double.TryParse(fclass, out freq))
{
FClass = FilterClassType.AdHoc;
_Frequency = freq;
}
else
{
FClass = FilterClassType.CFC1000;
_Frequency = (double)FilterClassType.CFC1000;
}
}
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (!(obj is FilterClass))
{
return false;
}
var filterObj = obj as FilterClass;
//FB 13120 needs this since the frequency would be different (-2 & 0) for unfiltered case
if (FClass == filterObj.FClass && FClass == FilterClassType.Unfiltered)
{
return true;
}
return FClass == filterObj.FClass && Frequency == filterObj.Frequency;
}
public int CompareTo(object filterClass)
{
IFilterClass fc = filterClass as FilterClass;
if (this == null)
{
if (fc == null)
{
// both null, equal
return 0;
}
// left null but not right
return -1;
}
if (fc == null)
{
// left not null, right null
return 1;
}
if (FClass != FilterClassType.None)
return fc.FClass == FilterClassType.None ? 1 : Frequency.CompareTo(fc.Frequency);
if (fc.FClass == FilterClassType.None)
{
return 0;
}
return -1;
}
/// <summary>
/// returns an identical hash index for any two "equal" filterclass objects
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
//.equals compares frequency and class, but we just need to guarantee that
//equal objects hash to the same index
return Convert.ToInt32(Frequency);
}
/// <summary>
/// FB 13120 Factory method to create a filter class
/// </summary>
/// <param name="fc"></param>
/// <param name="frequency"></param>
/// <returns></returns>
public static IFilterClass CreateFilterClass(FilterClassType fc, double frequency = 0)
{
if (fc == FilterClassType.AdHoc)
{
return new FilterClass(frequency);
}
else
{
return new FilterClass(fc);
}
}
/// <summary>
/// Get the filter class based on the string cfc
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static IFilterClass GetFilterClassFromString(string s)
{
if (string.IsNullOrEmpty(s)) return new FilterClass(FilterClassType.Unfiltered);
s = s.ToLower().Replace("cfc", "").Replace("hz", "").Trim();
double freq = 0;
if (double.TryParse(s, out freq))
{
switch (freq)
{
case 10:
return new FilterClass(FilterClassType.CFC10);
case 60:
return new FilterClass(FilterClassType.CFC60);
case 180:
return new FilterClass(FilterClassType.CFC180);
case 600:
return new FilterClass(FilterClassType.CFC600);
case 1000:
return new FilterClass(FilterClassType.CFC1000);
default:
return new FilterClass(FilterClassType.AdHoc, freq);
}
}
else
{
switch (s.ToLower())
{
case "unfiltered":
return new FilterClass(FilterClassType.Unfiltered);
case "none":
return new FilterClass(FilterClassType.None);
default:
return new FilterClass(FilterClassType.Unfiltered);
}
}
}
}
}

View File

@@ -0,0 +1,404 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using DTS.Common.Converters;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.Sensors;
using DTS.Common.Utilities.Logging;
namespace DTS.Common.Classes.Sensors
{
/// <summary>
/// InitialOffset is the replacement for InitialEU
/// it encompasses the old InitialOffset specified in EU with a offset of specifying it in mV @EU
/// Initial EU is a post data collection adjustment to engineering units recorded
/// </summary>
public class InitialOffset : Base.BasePropertyChanged
{
/// <summary>
/// copy constructor
/// </summary>
/// <param name="copy"></param>
public InitialOffset(InitialOffset copy)
{
if (null == copy) { return; }
EU = copy.EU;
MV = copy.MV;
Form = copy.Form;
}
/// <summary>
/// default constructor
/// </summary>
public InitialOffset()
{
Form = InitialOffsetTypes.None;
EU = 0D;
MV = 0D;
}
/// <summary>
/// constructor for the old format Initial EU (a single double representing offset in EU)
/// </summary>
/// <param name="d"></param>
public InitialOffset(double d)
{
Form = InitialOffsetTypes.EU;
EU = d;
MV = 0D;
}
/// <summary>
/// constructor for string from db
/// </summary>
/// <param name="s"></param>
public InitialOffset(string s)
{
FromDbSerializeString(s);
}
public override string ToString()
{
var converter = new EnumDescriptionTypeConverter(typeof(InitialOffsetTypes));
return converter.ConvertToString(Form);
}
/// <summary>
/// serializes to a db safe string
/// </summary>
/// <returns></returns>
public string ToDbSerializeString()
{
var s = new List<string>
{
Form.ToString(),
EU.ToString(System.Globalization.CultureInfo.InvariantCulture),
MV.ToString(System.Globalization.CultureInfo.InvariantCulture)
};
return string.Join(System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator, s.ToArray());
}
/// <summary>
/// deserializes from a string suitable for db storage
/// </summary>
/// <param name="input"></param>
public void FromDbSerializeString(string input)
{
if (string.IsNullOrWhiteSpace(input))
{
Form = InitialOffsetTypes.None;
EU = 0;
MV = 0;
return;
}
if (input == "EU")
{
Form = InitialOffsetTypes.EU;
EU = 0;
return;
}
if (input.Contains(InitialOffsets.MySeparator))
{
//we got an InputOffsets input. just take the first one
input = input.Split(new[] { InitialOffsets.MySeparator }, StringSplitOptions.RemoveEmptyEntries)[0];
}
var tokens = input.Split(new string[] { System.Globalization.CultureInfo.InvariantCulture.TextInfo.ListSeparator }, StringSplitOptions.None);
if (Enum.TryParse(tokens[0], out InitialOffsetTypes form))
{
Form = form;
if (tokens.Length < 3)
{
throw new System.IO.InvalidDataException($"Invalid InitialOffset number of parameters: {input}");
}
else
{
if (double.TryParse(tokens[1], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var d))
{
EU = d;
}
else { throw new FormatException($"Invalid InitialOffset EU format: {tokens[1]}"); }
if (double.TryParse(tokens[2], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out d))
{
MV = d;
}
else { throw new FormatException($"Invalid InitialOffset MV format: {tokens[2]}"); }
}
}
else { throw new System.IO.InvalidDataException("Invalid InitialOffset form: " + tokens[0]); }
}
private InitialOffsetTypes _form;
/// <summary>
/// the format this intial offset instance is in
/// </summary>
public InitialOffsetTypes Form
{
get => _form;
set => SetProperty(ref _form, value, Fields.Form.ToString());
}
//FB18158 Don't allow removal of None option
public System.Windows.Visibility InitialOffsetVisibility
{
get => Form != InitialOffsetTypes.None ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden;
}
private double _eu = 0D;
/// <summary>
/// EU value. In the case of Form == EU, this is the offset in EU
/// In. the form of EU@mV, this is the EU@mV value, and offset in EU still needs to be calculated
/// GetInitialEUValue calculates the offset in eu
/// this value is not used for InitialOffset format None
/// </summary>
public double EU
{
get => _eu;
set => SetProperty(ref _eu, value, Fields.EU.ToString());
}
private double _mv = 0D;
/// <summary>
/// mV value, only applies for the format EU@mV
/// this is the value in mV that The value in EU is observed at by a calibrated instrument
/// </summary>
public double MV
{
get => _mv;
set => SetProperty(ref _mv, value, Fields.MV.ToString());
}
private enum Fields
{
Form,
EU,
MV
}
/// <summary>
/// Displays initial offset structure to string
/// created for FB5429
/// </summary>
/// <param name="NONEFormatString">string resource similar to "None"</param>
/// <param name="EUFormatString">string resource similar to "EU"</param>
/// <param name="mVFormatString">string resource similar to "mV"</param>
/// <returns></returns>
public string ToDisplayString(string NONEFormatString, string EUFormatString, string mVFormatString)
{
var sb = new StringBuilder();
switch (Form)
{
case InitialOffsetTypes.EU:
case InitialOffsetTypes.LHS:
case InitialOffsetTypes.RHS:
case InitialOffsetTypes.FRONTAL:
sb.AppendFormat("{0} {1}", EU, EUFormatString);
break;
case InitialOffsetTypes.EUAtMV:
sb.AppendFormat("{0} {1} @ {2} {3}", EU, EUFormatString, MV, mVFormatString);
break;
case InitialOffsetTypes.None:
sb.AppendFormat("{0}", NONEFormatString);
break;
default:
break;
}
return sb.ToString();
}
/// <summary>
/// Compares attributes to another InitialOffset object
/// created for FB5429
/// </summary>
/// <param name="obj">an InitialOffset object</param>
/// <returns>if contents are equal</returns>
public override bool Equals(object obj)
{
if (obj is InitialOffset io)
{
var fields = Enum.GetValues(typeof(Fields)).Cast<Fields>().ToArray();
foreach (var field in fields)
{
switch (field)
{
case Fields.Form: if (io.Form != Form) { return false; } break;
case Fields.EU: if (io.EU != EU) { return false; } break;
case Fields.MV: if (io.MV != MV) { return false; } break;
default:
throw new NotSupportedException("InitialOffset::Equals Unknown field " + field);
}
}
return true;
}
return base.Equals(obj);
}
}
public class InitialOffsets : IInitialOffsets
{
public InitialOffset[] Offsets { get; set; } = new InitialOffset[] { };
//FB18158 Always add None option to InitialOffsets
private void SeedNoneInInitialOffsets()
{
if (Offsets.Any(p => p.Form == InitialOffsetTypes.None))
{
return;
}
List<InitialOffset> initialOffsets = new List<InitialOffset>();
initialOffsets.Add(new InitialOffset());
foreach (var io in Offsets)
{
initialOffsets.Add(io);
}
Offsets = initialOffsets.ToArray();
}
public InitialOffset DefaultOffset
{
get
{
//30442 Don't default InitialOffset to None if other options exist
if (null != Offsets && Offsets.Any())
{
if ((Offsets.Count() > 1) && (Offsets[0].Form == InitialOffsetTypes.None))
{
return Offsets[1];
}
else
{
return Offsets[0];
}
}
else
{
return new InitialOffset();
}
}
}
public InitialOffsets(InitialOffsets copy)
{
InitialOffset[] offsets = new InitialOffset[copy.Offsets.Length];
for (int i = 0; i < copy.Offsets.Length; i++)
{
offsets[i] = new InitialOffset(copy.Offsets[i]);
}
Offsets = offsets;
SeedNoneInInitialOffsets();
}
/// <summary>
/// This produces an instance of the class based on an existing instance,
/// but without the first Initial Offset, only additional Initial Offsets
/// </summary>
/// <param name="copy"></param>
/// <param name="numAdditionalInitialOffsets"></param>
public InitialOffsets(InitialOffsets copy, int numAdditionalInitialOffsets)
{
InitialOffset[] offsets = new InitialOffset[numAdditionalInitialOffsets];
for (int i = 0; i < numAdditionalInitialOffsets; i++)
{
offsets[i] = new InitialOffset(copy.Offsets[i + 1]);
}
Offsets = offsets;
SeedNoneInInitialOffsets();
}
public InitialOffsets()
{
Offsets = new InitialOffset[] { new InitialOffset() };
SeedNoneInInitialOffsets();
}
public InitialOffsets(string offsets)
{
FromSerializedString(offsets);
SeedNoneInInitialOffsets();
}
public InitialOffsets(InitialOffset startingOffset)
{
Offsets = new InitialOffset[] { startingOffset };
SeedNoneInInitialOffsets();
}
public override bool Equals(object obj)
{
if (obj is InitialOffsets r)
{
if (r.Offsets.Length != Offsets.Length) { return false; }
for (var i = 0; i < r.Offsets.Length; i++)
{
if (!r.Offsets[i].Equals(Offsets[i])) { return false; }
}
return true;
}
return base.Equals(obj);
}
public void FromSerializedString(string s)
{
try
{
var tokens = s.Split(new string[] { MySeparator }, StringSplitOptions.None);
for (var i = 0; i < tokens.Length; i++) { tokens[i] = tokens[i].Replace(MySeparatorBackup, MySeparator); }
var offsets = new List<InitialOffset>();
foreach (string token in tokens)
{
try
{
offsets.Add(new InitialOffset(token));
}
catch (Exception ex) { APILogger.Log(ex); }
}
Offsets = offsets.ToArray();
SeedNoneInInitialOffsets();
}
catch( Exception ex)
{
APILogger.Log(ex);
}
}
internal const string MySeparator = "__x__";
internal const string MySeparatorBackup = "___xx___";
public string ToSerializedString()
{
var offsets = new List<string>();
foreach (var r in Offsets) { offsets.Add(r.ToDbSerializeString()); }
for (int i = 0; i < offsets.Count; i++)
{
Trace.Assert(!offsets[i].Contains(MySeparatorBackup));
offsets[i] = offsets[i].Replace(MySeparator, MySeparatorBackup);
}
return string.Join(MySeparator, offsets.ToArray());
}
public string ToDisplayString(string averageOverTimeFormatString, string diagnosticLevelFormatString, string absoluteZeroFormatString)
{
var sb = new StringBuilder();
for (var i = 0; i < Offsets.Length; i++)
{
if (i > 0) { sb.AppendLine(); }
var s = Offsets[i].ToDisplayString(averageOverTimeFormatString, diagnosticLevelFormatString, absoluteZeroFormatString);
if (!string.IsNullOrEmpty(s))
{
sb.Append(s);
}
}
return sb.ToString();
}
public override string ToString()
{
return ToDisplayString(Strings.Strings.SensorFields_InitialOffset_AverageOverTimeFormat, Strings.Strings.SensorFields_InitialOffset_DiagnosticLevelFormat,
Strings.Strings.SensorFields_InitialOffset_AbsoluteZeroFormat);
}
}
}

View File

@@ -0,0 +1,699 @@
using System;
using System.Collections.Generic;
using System.Text;
using DTS.Common.Enums.Sensors;
namespace DTS.Common.Classes.Sensors
{
public class LinearizationFormula
{
private bool _bIsValid;
public bool IsValid() { return _bIsValid; }
public void MarkValid(bool bValid)
{
_bIsValid = bValid;
}
// Translation
public NonLinearSLICEWareStyles NonLinearSliceWareStyle
{
get => (NonLinearSLICEWareStyles)NonLinearStyle;
set => NonLinearStyle = (NonLinearStyles)value;
}
public NonLinearStyles NonLinearStyle { get; set; } = NonLinearStyles.Polynomial; // Dont make the default style one that locks a specific zero-method FB 10323
public double PolynomialSensitivity { get; set; } = 1D;
public double LinearizationExponent { get; set; } = 1D;
/// <summary>
/// THIS IS MM/V, (UI has already been updated, we need to update the variable name)
/// </summary>
private double _mmPerMV;
public double MMPerV
{
get => _mmPerMV;
set => _mmPerMV = value;
}
public double MVAt0MM { get; set; }
public double Slope { get; set; }
public double Intercept { get; set; }
public double CalibrationFactor { get; set; }
public double ZeroPositionIntercept { get; set; }
public LinearizationFormula()
{
ZeroPositionIntercept = 0D;
CalibrationFactor = 0D;
Intercept = 0D;
_coefficients = new List<double>(new double[] { 0, 0, 0, 0 });
_exponents = new List<double>(new double[] { 0, 1, 2, 3 });
}
public LinearizationFormula(LinearizationFormula copy)
{
UsemVOverVForPolys = copy.UsemVOverVForPolys;
_bIsValid = copy._bIsValid;
_coefficients = new List<double>(copy._coefficients.ToArray());
_exponents = new List<double>(copy._exponents.ToArray());
Intercept = copy.Intercept;
LinearizationExponent = copy.LinearizationExponent;
_mmPerMV = copy._mmPerMV;
MVAt0MM = copy.MVAt0MM;
Slope = copy.Slope;
NonLinearStyle = copy.NonLinearStyle;
_coefficients = new List<double>(copy._coefficients);
_exponents = new List<double>(copy._exponents);
PolynomialSensitivity = copy.PolynomialSensitivity;
ZeroPositionIntercept = copy.ZeroPositionIntercept;
CalibrationFactor = copy.CalibrationFactor;
}
public double GetCoefficient(double exponent)
{
for (var i = 0; i < _exponents.Count && i < _coefficients.Count; i++)
{
if (_exponents[i] == exponent) { return _coefficients[i]; }
}
return 0;
}
public void SetCoefficient(double exponent, double coefficient)
{
for (var i = 0; i < _exponents.Count && i < _coefficients.Count; i++)
{
if (_exponents[i] == exponent) { _coefficients[i] = coefficient; return; }
}
}
public double GetLinearizedValue(double input, double excitation, bool? isProportional = null)
{
if (NonLinearStyle != NonLinearStyles.Polynomial && input <= 0)
{
//ir-tracc should never be < 0, however we may get readings less than zero due to
//noise and other factors, treat these as positive near to zero
input = .001;
}
//first linearize
input /= 1000D;//assume input is in mV and we want it in Volts
input = Math.Pow(input, LinearizationExponent);
switch (NonLinearStyle)
{
case NonLinearStyles.IRTraccDiagnosticsZero:
return GetEUDiagnosticsZero(input);
case NonLinearStyles.IRTraccManual:
return GetEUIRTraccManual(input);
case NonLinearStyles.IRTraccZeroMMmV:
return GetEUZeroMMmV(input);
case NonLinearStyles.IRTraccAverageOverTime:
return GetEUAverageOverTime(input);
case NonLinearStyles.Polynomial:
//FB 29728 pass parameter isProportional, consider null as true to use the existing formula to divide by excitation
return GetEUPolynomial(input, excitation, isProportional ?? true);
case NonLinearStyles.IRTraccCalFactor:
return GetEUIRTraccCalFactor(input);
default:
throw new NotSupportedException("unknown format: " + NonLinearStyle);
}
}
private double GetEUIRTraccCalFactor(double volts)
{
return volts * CalibrationFactor + ZeroPositionIntercept;
}
private double GetEUIRTraccManual(double volts)
{
return (volts - Intercept) / Slope;
}
public bool UsemVOverVForPolys { get; set; } = true;
private double GetEUZeroMMmV(double volts)
{
var input = MVAt0MM / 1000D;
input = Math.Pow(input, LinearizationExponent);
if (double.IsNaN(input) || double.IsNegativeInfinity(input) || double.IsPositiveInfinity(input))
{
return volts * MMPerV;
}
return (volts * MMPerV - MMPerV * input);
}
private List<double> _coefficients = new List<double>();
private List<double> _exponents = new List<double>();
private double GetEUPolynomial(double volts, double excitation, bool isProportional)
{
//per J2517
//3.4 Use of the Calibration Coefficients
//The potentiometer assembly should be re-installed in the dummy without any mechanical adjustment of the
//potentiometer. Prior to a crash test, the original zero offset level must be preserved by either not zeroing the
//potentiometer (by signal conditioning or post-processing) or the amount that was zeroed must be added during postprocessing.
//During the test the absolute voltage output time history should be recorded. This voltage signal is then
//converted to engineering units by:
//1. Convert voltage signal to mV/V at the sensor. This is the sensor reading S.
//2. Convert the sensor reading S to displacement D by using the equation:
//D = A*S^3 + B*S^2 + C*S + M (Eq. 2)
//where:
//D is the displacement relative to the thorax design position in mm
//S is the sensor output reading in mV/V
//A, B, C, and M are the calibration coefficients
//NOTE: Make sure to use sufficient significant digits on all coefficients to assure accuracy of the conversion to
//engineering units. It is recommended to use 5 significant digits (example 0.000012345).
//double mV = volts * 1000D;
//double gain = 1D;
//mV = mV / (gain * excitation);
//if (0 != PolynomialSensitivity && 1!= PolynomialSensitivity) { mV /= PolynomialSensitivity; }
//double eu = 0D;
//for (int i = 0; i < _coefficients.Count && i < _exponents.Count; i++)
//{
// eu += _coefficients[i] * Math.Pow(mV, _exponents[i]);
//}
//return eu;
//CHANGED FOR GM TESTING
if (0 != PolynomialSensitivity && 1 != PolynomialSensitivity)
{
volts /= PolynomialSensitivity;
}
var voltsOverV = 0D;
//FB 29728 if is not proportinal then excitation voltage should be 1
if (!isProportional)
{
excitation = 1D;
}
if (UsemVOverVForPolys)
{
//convert to mV first
voltsOverV = volts * 1000D / excitation;
}
else
{
//used by GM
voltsOverV = volts / excitation;
}
double eu = 0;
for (var i = 0; i < _coefficients.Count && i < _exponents.Count; i++)
{
if (_exponents[i] != 0)
{
eu += _coefficients[i] * Math.Pow(voltsOverV, _exponents[i]);
}
else
{
eu += _coefficients[i];
}
}
return eu;
}
/// <summary>
/// MvAt0MM set at diagnostics
/// </summary>
/// <param name="volts"></param>
/// <returns></returns>
private double GetEUDiagnosticsZero(double volts)
{
//double input = MVAt0MM/1000D;
//input = System.Math.Pow(input,LinearizationExponent);
var input = double.NaN;
if (double.IsNaN(input) || double.IsPositiveInfinity(input) || double.IsNegativeInfinity(input))
{
return volts * MMPerV;
}
return volts * MMPerV - MMPerV * input;
}
/// <summary>
/// MVAt0MM set by diagnostics and then later on at
/// Average Over Time
/// </summary>
/// <param name="volts"></param>
/// <returns></returns>
private double GetEUAverageOverTime(double volts)
{
//double input = MVAt0MM / 1000D;
//input = System.Math.Pow(input, LinearizationExponent);
var input = double.NaN;
if (double.IsNaN(input) || double.IsNegativeInfinity(input) || double.IsPositiveInfinity(input))
{
return volts * MMPerV;
}
return volts * MMPerV - MMPerV * input;
}
public string ToSLICEWareSerializeString()
{
if (!_bIsValid) { return ""; }
var sb = new StringBuilder();
sb.AppendFormat("{0}_", NonLinearStyle);
switch (NonLinearStyle)
{
case NonLinearStyles.IRTraccDiagnosticsZero:
sb.Append(ToIRTraccDiagnosticZeroString());
break;
case NonLinearStyles.IRTraccManual:
sb.Append(ToIRTraccManualString());
break;
case NonLinearStyles.IRTraccZeroMMmV:
sb.Append(ToIRTraccZeroMMmVString());
break;
case NonLinearStyles.IRTraccAverageOverTime:
sb.Append(ToIRTraccAverageOverTimeString());
break;
case NonLinearStyles.Polynomial:
sb.Append(ToSLICEWarePolynomialString());
break;
case NonLinearStyles.IRTraccCalFactor:
throw new NotSupportedException("CalFactor not supported in SLICEWare");
default:
throw new NotSupportedException("unknown type: " + NonLinearStyle);
}
return sb.ToString();
}
/// <summary>
/// serializes to a string of the format "c0xe0 c1xe1...cnxen"
/// this will allow us arbitrary length polynomials and fractional exponents.
/// </summary>
/// <returns></returns>
public string ToSerializeString()
{
if (!_bIsValid) { return ""; }
var sb = new StringBuilder();
sb.AppendFormat("{0}_", NonLinearStyle);
switch (NonLinearStyle)
{
case NonLinearStyles.IRTraccDiagnosticsZero:
sb.Append(ToIRTraccDiagnosticZeroString());
break;
case NonLinearStyles.IRTraccManual:
sb.Append(ToIRTraccManualString());
break;
case NonLinearStyles.IRTraccZeroMMmV:
sb.Append(ToIRTraccZeroMMmVString());
break;
case NonLinearStyles.IRTraccAverageOverTime:
sb.Append(ToIRTraccAverageOverTimeString());
break;
case NonLinearStyles.Polynomial:
sb.Append(ToPolynomialString());
break;
case NonLinearStyles.IRTraccCalFactor:
sb.Append(ToIRTraccCalFactorString());
break;
default:
throw new NotSupportedException("unknown type: " + NonLinearStyle);
}
return sb.ToString();
}
public string ToIRTraccDiagnosticZeroString()
{
return $"{MMPerV.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public string ToIRTraccCalFactorString()
{
return $"{CalibrationFactor.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{ZeroPositionIntercept.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public void FromIRTraccCalFactorString(string s, System.Globalization.CultureInfo culture)
{
var tokens = s.Split('x');
if (tokens.Length < 3) { throw new NotSupportedException("Invalid CalFactor format: " + s); }
CalibrationFactor = double.Parse(tokens[0], culture);
LinearizationExponent = double.Parse(tokens[1], culture);
ZeroPositionIntercept = double.Parse(tokens[2], culture);
}
public void FromIRTraccDiagnosticZeroString(string s, System.Globalization.CultureInfo culture)
{
var tokens = s.Split('x');
if (tokens.Length < 2) { throw new NotSupportedException("Invalid DiagnosticsZero format: " + s); }
MMPerV = double.Parse(tokens[0], culture);
LinearizationExponent = double.Parse(tokens[1], culture);
}
public string ToIRTraccManualString()
{
return $"{Slope.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{Intercept.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public void FromIRTraccManualString(string s, System.Globalization.CultureInfo culture)
{
var tokens = s.Split('x');
if (tokens.Length < 3) { throw new NotSupportedException("Invalid IRTraccManual format: " + s); }
Slope = double.Parse(tokens[0], culture);
Intercept = double.Parse(tokens[1], culture);
LinearizationExponent = double.Parse(tokens[2], culture);
}
public string ToIRTraccZeroMMmVString()
{
return $"{MMPerV.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{MVAt0MM.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public string ToSLICEWarePolynomialString()
{
//SLICEWare is the reverse order of our DataPRO Database
var sb = new StringBuilder();
for (var i = _exponents.Count - 1; i >= 0; i--)
{
if (i != _exponents.Count - 1) { sb.Append(","); }
sb.AppendFormat("{0}x{1}", _coefficients[i].ToString(System.Globalization.CultureInfo.InvariantCulture),
_exponents[i].ToString(System.Globalization.CultureInfo.InvariantCulture));
}
sb.AppendFormat(",S={0}", PolynomialSensitivity.ToString(System.Globalization.CultureInfo.InvariantCulture));
return sb.ToString();
}
public string ToPolynomialString()
{
var sb = new StringBuilder();
for (var i = 0; i < _coefficients.Count && i < _exponents.Count; i++)
{
if (i > 0) { sb.Append(","); }
sb.AppendFormat("{0}x{1}", _coefficients[i].ToString(System.Globalization.CultureInfo.InvariantCulture),
_exponents[i].ToString(System.Globalization.CultureInfo.InvariantCulture));
}
sb.AppendFormat(",S={0},mV={1}",
PolynomialSensitivity.ToString(System.Globalization.CultureInfo.InvariantCulture),
UsemVOverVForPolys.ToString(System.Globalization.CultureInfo.InvariantCulture));
return sb.ToString();
}
public double[] PolynomialCoefficients
{
get => _coefficients.ToArray();
set => _coefficients = new List<double>(value);
}
public double[] PolynomialExponents
{
get => _exponents.ToArray();
set => _exponents = new List<double>(value);
}
public string ToIRTraccAverageOverTimeString()
{
return $"{MMPerV.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public void FromIRTraccAverageOverTimeString(string s, System.Globalization.CultureInfo culture)
{
var tokens = s.Split('x');
if (tokens.Length < 2) { throw new NotSupportedException("Invalid IRTRaccAverageOverTime format: " + s); }
MMPerV = double.Parse(tokens[0], culture);
LinearizationExponent = double.Parse(tokens[1], culture);
}
public void FromIRTraccZeroMMmVString(string s, System.Globalization.CultureInfo culture)
{
var tokens = s.Split('x');
if (tokens.Length < 3) { throw new NotSupportedException("Invalid IRTraccZeroMMmV format: " + s); }
MMPerV = double.Parse(tokens[0], culture);
MVAt0MM = double.Parse(tokens[1], culture);
LinearizationExponent = double.Parse(tokens[2], culture);
}
public void FromPolynomialString(string s, System.Globalization.CultureInfo culture)
{
_coefficients.Clear();
_exponents.Clear();
var tokens = s.Split(',');
foreach (var t in tokens)
{
var subtokens = t.Split(new[] { 'x' }, StringSplitOptions.RemoveEmptyEntries);
if (2 == subtokens.Length)
{
if (double.TryParse(subtokens[0], System.Globalization.NumberStyles.Float, culture, out var d))
{
_coefficients.Add(d);
_exponents.Add(double.Parse(subtokens[1], culture));
}
else
{
PolynomialSensitivity = double.Parse(subtokens[1], culture);
}
}
else
{
subtokens = subtokens[0].Split('=');
if (subtokens.Length == 2)
{
switch (subtokens[0])
{
case "S":
PolynomialSensitivity = double.Parse(subtokens[1], culture);
break;
case "mV":
UsemVOverVForPolys = Convert.ToBoolean(subtokens[1], culture);
break;
}
}
}
}
}
public void FromSerializeString(string s, System.Globalization.CultureInfo culture)
{
if (string.IsNullOrEmpty(s)) { _bIsValid = false; return; }
if (s.Equals("1") || s.Equals("0") || s.Equals("1 ")) { _bIsValid = false; return; }
var tokens = s.Split('_');
if (tokens.Length < 2) { throw new NotSupportedException("unsupported Linearization Formula Format"); }
var style = (NonLinearStyles)Enum.Parse(typeof(NonLinearStyles), tokens[0], true);
NonLinearStyle = style;
switch (NonLinearStyle)
{
case NonLinearStyles.IRTraccDiagnosticsZero:
FromIRTraccDiagnosticZeroString(tokens[1], culture);
_bIsValid = true;
break;
case NonLinearStyles.IRTraccManual:
FromIRTraccManualString(tokens[1], culture);
_bIsValid = true;
break;
case NonLinearStyles.IRTraccZeroMMmV:
FromIRTraccZeroMMmVString(tokens[1], culture);
_bIsValid = true;
break;
case NonLinearStyles.Polynomial:
FromPolynomialString(tokens[1], culture);
_bIsValid = true;
break;
case NonLinearStyles.IRTraccAverageOverTime:
FromIRTraccAverageOverTimeString(tokens[1], culture);
_bIsValid = true;
break;
case NonLinearStyles.IRTraccCalFactor:
FromIRTraccCalFactorString(tokens[1], culture);
_bIsValid = true;
break;
default:
throw new NotSupportedException("Unknown format: " + NonLinearStyle);
}
}
public void FromSerializeString(string s)
{
FromSerializeString(s, System.Globalization.CultureInfo.InvariantCulture);
}
public void FromTDCSerializeString()
{
_bIsValid = true;
}
/// <summary>
/// Will return a display string for a nonlinear calibration based on N4 formating
/// </summary>
public string ToDisplayString()
{
return ToDisplayString("N4");
}
/// <summary>
/// Will return a display string for a nonlinear calibration based on 1st paramater formating string
/// </summary>
/// <param name="nonlinearFormat"></param>
/// <returns></returns>
public string ToDisplayString(string nonlinearFormat)
{
if (string.IsNullOrEmpty(nonlinearFormat)) { nonlinearFormat = "N4"; }
switch (NonLinearStyle)
{
case NonLinearStyles.Polynomial:
{
return ToPolynomial(nonlinearFormat);
}
case NonLinearStyles.IRTraccZeroMMmV:
{
return $"mV = {MVAt0MM:n4}, {MMPerV:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
}
case NonLinearStyles.IRTraccManual:
{
return $"((V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})-{Intercept:n4})/{Slope:n4}";
}
case NonLinearStyles.IRTraccDiagnosticsZero:
{
return $"{MMPerV:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
}
case NonLinearStyles.IRTraccAverageOverTime:
{
return $"{MMPerV:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
}
case NonLinearStyles.IRTraccCalFactor:
{
return $"{ZeroPositionIntercept:n4}+{CalibrationFactor:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
}
default:
return string.Empty;
}
}
private string ToPolynomial(string nonlinearFormat)
{
if (string.IsNullOrEmpty(nonlinearFormat)) { nonlinearFormat = "N4"; }
var sb = new StringBuilder();
var termNumber = PolynomialCoefficients.Length - 1;
foreach (var x in PolynomialCoefficients)
{
if (PolynomialCoefficients[termNumber] == 0)
{
termNumber--;
continue;
}
double coeff = HandleSign(termNumber);
sb.Append(coeff.ToString(nonlinearFormat));
if (PolynomialExponents[termNumber] != 0)
{
sb.Append("x");
if (PolynomialExponents[termNumber] != 1)
{
sb.Append(ToSuperScript(PolynomialExponents[termNumber].ToString("N0")));
}
}
if (termNumber > 0)
{
// Coerricients are Displayed in absolute value. We need to combine the sign with the addition symbol
sb.Append(PolynomialCoefficients[termNumber - 1] > 0 ? " + " : " - ");
}
termNumber--;
}
return sb.ToString();
}
private double HandleSign(int termNumber)
{
double coeff = PolynomialCoefficients[termNumber];
// Let the appended math symbol handle sign unless we're the first term.
if (termNumber != PolynomialCoefficients.Length - 1)
{
coeff = Math.Abs(coeff);
}
return coeff;
}
private string ToSuperScript(string source)
{
var superScript = new StringBuilder();
foreach (var c in source)
{
switch (c)
{
case '-':
superScript.Append('\u207B');
break;
case '.':
superScript.Append('\u00B7');
break;
case '1':
superScript.Append('\u00B9');
break;
case '2':
superScript.Append('\u00B2');
break;
case '3':
superScript.Append('\u00B3');
break;
case '4':
superScript.Append('\u2074');
break;
case '5':
superScript.Append('\u2075');
break;
case '6':
superScript.Append('\u2076');
break;
case '7':
superScript.Append('\u2077');
break;
case '8':
superScript.Append('\u2078');
break;
case '9':
superScript.Append('\u2079');
break;
case '0':
superScript.Append('\u2070');
break;
case '\'':
superScript.Append('\u02C8');
break;
case ',':
superScript.Append('\u22C5'); // there is no unicode superscript comma. this comes close
break;
case '\u00A0':
superScript.Append('\u2009'); // unicode 'thin' space
break;
default:
superScript.Append('\u207F');
break;
}
}
return superScript.ToString();
}
/*
* we are given an equation in the form of y = ax^1 + b, except x and y are backwards for us (y=V where we'd prefer X was voltage, so we switch it)
* y/a - b/a = x, and then switch y and x, (1/a)x^1 -(b/a)x^0 = y
* now we want to get the coefficient of the first equation, which is "a", we get this by taking the inverse
* we get b on the other hand by taking -1 * (b/a)*a. if we have the "coefficient", we have a
*/
/*
public double GetIRTraccCoefficient()
{
foreach (Factor f in Factors)
{
if (f.Exponent == 1D) { return System.Math.Pow(f.Coefficient, -1); }
}
return 1D; //0 doesn't make sense for ir
}
public double GetIRTraccConstant()
{
foreach (Factor f in Factors)
{
if (f.Exponent == 0D) { return -1D * GetIRTraccCoefficient() * f.Coefficient; }
}
return 0D;
}
public void SetIRTraccFactor(double coefficient, double constant)
{
if (0 == coefficient)
{
//well this doesn't make any sense ...
coefficient = 1;
}
Factors = new Factor[]
{
new Factor(1/coefficient,1),
new Factor(-constant/coefficient,0),
};
}*/
}
}

View File

@@ -0,0 +1,113 @@
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.Sensors;
using System;
using System.Collections.Generic;
namespace DTS.Common.Classes.Sensors
{
/// <summary>
/// internal helper class to avoid passing a huge number of parameters between methods
/// right now it's needed both in the Wizard CSV import code and in DataPRO CSV import code
/// but it can probably be moved to only be in Wizard CSV import code when DataPRO CSV import code is removed
/// for now it lives here.
/// </summary>
public class ParseParameters
{
public bool ImportContainedSensorRanges { get; set; } = false;
private ISensorData _sd;
public ISensorData SensorData { get => _sd; set => _sd = value; }
private IFormatProvider _importCulture;
public IFormatProvider ImportCulture { get => _importCulture; set => _importCulture = value; }
private List<string> _errors;
public List<string> Errors { get => _errors; set => _errors = value; }
private double _dIrTraccExponent;
public double IrtraccExponent { get => _dIrTraccExponent; set => _dIrTraccExponent = value; }
private ISensorCalibration _sc;
public ISensorCalibration SensorCal { get => _sc; set => _sc = value; }
private double _dSensitivity;
public double Sensitivity { get => _dSensitivity; set => _dSensitivity = value; }
private bool _bSavedIsProportional;
public bool SavedIsProportional { get => _bSavedIsProportional; set => _bSavedIsProportional = value; }
private bool _savedRemoveOffset;
public bool SavedRemoveOffset { get => _savedRemoveOffset; set => _savedRemoveOffset = value; }
private bool _stripBackslash;
public bool StripBackslash { get => _stripBackslash; set => _stripBackslash = value; }
private double _dOriginalOffset = double.NaN;
public double OriginalOffset { get => _dOriginalOffset; set => _dOriginalOffset = value; }
private ZeroMethodType _zmt;
public ZeroMethodType ZeroType { get => _zmt; set => _zmt = value; }
private double _zeroMethodEnd;
public double ZeroEnd
{
get => _zeroMethodEnd; set => _zeroMethodEnd = value;
}
private double _zeroMethodStart;
public double ZeroStart { get => _zeroMethodStart; set => _zeroMethodStart = value; }
private ISquibSettingDefaults _squibDefaults;
public ISquibSettingDefaults SquibDefaults
{
get => _squibDefaults; set => _squibDefaults = value;
}
private IDigitalOutDefaults _digitalOutDefaults;
public IDigitalOutDefaults DigitalOutDefaults
{
get => _digitalOutDefaults; set => _digitalOutDefaults = value;
}
private Dictionary<string, string> _sensorGroupNameLookup;
public Dictionary<string, string> SensorGroupNameLookup
{
get => _sensorGroupNameLookup; set => _sensorGroupNameLookup = value;
}
private Dictionary<string, string> _sensorGroupTypeLookup;
public Dictionary<string, string> SensorGroupTypeLookup
{
get => _sensorGroupTypeLookup; set => _sensorGroupTypeLookup = value;
}
private Dictionary<string, string> _groupNameToTestObjectLookup;
public Dictionary<string, string> GroupNameToTestObjectLookup { get => _groupNameToTestObjectLookup; set => _groupNameToTestObjectLookup = value; }
private string _sensorTestObject;
public string SensorTestObject { get => _sensorTestObject; set => _sensorTestObject = value; }
private bool _bUseISOCodeFilterMapping;
public bool UseISOCodeFilterMapping { get => _bUseISOCodeFilterMapping; set => _bUseISOCodeFilterMapping = value; }
private bool _bUseZeroForUnfiltered;
public bool UseZeroForUnfiltered { get => _bUseZeroForUnfiltered; set => _bUseZeroForUnfiltered = value; }
private Dictionary<string, string> _SensorISOCode;
public Dictionary<string, string> SensorISOCode { get => _SensorISOCode; set => _SensorISOCode = value; }
private Dictionary<string, string> _SensorISOChannelName;
public Dictionary<string, string> SensorISOChannelName { get => _SensorISOChannelName; set => _SensorISOChannelName = value; }
private Dictionary<string, string> _SensorUserCode;
public Dictionary<string, string> SensorUserCode { get => _SensorUserCode; set => _SensorUserCode = value; }
private Dictionary<string, string> _SensorUserChannelName;
public Dictionary<string, string> SensorUserChannelName { get => _SensorUserChannelName; set => _SensorUserChannelName = value; }
private Dictionary<string, string> _SensorDASSerialNumber;
public Dictionary<string, string> SensorDASSerialNumber { get => _SensorDASSerialNumber; set => _SensorDASSerialNumber = value; }
private Dictionary<string, int> _SensorDASChannelIndex;
public Dictionary<string, int> SensorDASChannelIndex { get => _SensorDASChannelIndex; set => _SensorDASChannelIndex = value; }
}
}

View File

@@ -0,0 +1,216 @@
using DTS.Common.Base;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.Sensors;
using DTS.Common.Utilities.Logging;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Globalization;
using System.Linq;
namespace DTS.Common.Classes.Sensors
{
public class SensorCalDbRecord : BasePropertyChanged, ISensorCalDbRecord
{
public bool LinearAdded
{
get => NonLinear && Records.Records[0].Poly.NonLinearStyle == NonLinearStyles.Polynomial &&
Records.Records.Length > 1 && ZeroMethods.Methods.Length > 1;
}
private int? _calibrationId = null;
/// <summary>
/// database id, if known, for calibration, null indicates not known
/// 13065 Sensor "First Use" Date
/// </summary>
[Key]
public int? CalibrationId
{
get => _calibrationId;
set => SetProperty(ref _calibrationId, value, "CalibrationId");
}
protected string _serialNumber;
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
protected DateTime _calibrationDate;
[Column(TypeName = "datetime")]
public DateTime CalibrationDate
{
get => _calibrationDate;
set => SetProperty(ref _calibrationDate, value, "CalibrationDate");
}
protected string _userName = "";
[Required]
[StringLength(50)]
public string Username
{
get => _userName;
set => SetProperty(ref _userName, value, "Username");
}
private bool _localOnly;
public bool LocalOnly
{
get => _localOnly;
set => SetProperty(ref _localOnly, value, "LocalOnly");
}
private bool _nonLinear;
public bool NonLinear
{
get => _nonLinear;
set
{
SetProperty(ref _nonLinear, value, "NonLinear");
if (!value) return;
Records.Records[0].Sensitivity = 1D;
//FB 29728 don't make IsProportinal false
//IsProportional = false;
RemoveOffset = false;
}
}
private ICalibrationRecords _records = new CalibrationRecords();
[Required]
[StringLength(255)]
public ICalibrationRecords Records
{
get => _records;
set => SetProperty(ref _records, value, "Records");
}
private DateTime _modifyDate;
[Column(TypeName = "datetime")]
public DateTime ModifyDate
{
get => _modifyDate;
set => SetProperty(ref _modifyDate, value, "ModifyDate");
}
private bool _isProportional;
public bool IsProportional
{
get => _isProportional;
set => SetProperty(ref _isProportional, value, "IsProportional");
}
private bool _removeOffset;
public bool RemoveOffset
{
get => _removeOffset;
set => SetProperty(ref _removeOffset, value, "RemoveOffset");
}
//FB 43152
private SensitivityInspectionType _sensitivityInspection;
public SensitivityInspectionType SensitivityInspection
{
get => _sensitivityInspection;
set => SetProperty(ref _sensitivityInspection, value, "SensitivityInspection");
}
//FB 43141
private string _calibrationNote = string.Empty;
[StringLength(2048)]
public string CalibrationNote
{
get => _calibrationNote;
set => SetProperty(ref _calibrationNote, value, "CalibrationNote");
}
//FB 43265
private int _usageCount;
public int UsageCount
{
get => _usageCount;
set => SetProperty(ref _usageCount, value, "UsageCount");
}
private ZeroMethods _zeroMethods = new ZeroMethods();
[Required]
[StringLength(255)]
public ZeroMethods ZeroMethods
{
get => _zeroMethods;
set => SetProperty(ref _zeroMethods, value, "ZeroMethods");
}
private string[] _certificationDocuments = new string[0];
[Required]
[StringLength(2048)]
public string[] CertificationDocuments
{
get => _certificationDocuments;
set => SetProperty(ref _certificationDocuments, value, "CertificationDocuments");
}
//FB18158 It's None the default now not EU
private InitialOffsets _initialOffsets = new InitialOffsets(new InitialOffset());
public InitialOffsets InitialOffsets
{
get => _initialOffsets;
set => SetProperty(ref _initialOffsets, value, "InitialOffsets");
}
public SensorCalDbRecord() { }
public SensorCalDbRecord(ISensorCalDbRecord copy)
{
CalibrationDate = copy.CalibrationDate;
LocalOnly = copy.LocalOnly;
SerialNumber = copy.SerialNumber;
Username = copy.Username;
Records = new CalibrationRecords(copy.Records);
NonLinear = copy.NonLinear;
IsProportional = copy.IsProportional;
ModifyDate = copy.ModifyDate;
var list = new List<string>(copy.CertificationDocuments);
CertificationDocuments = list.ToArray();
RemoveOffset = copy.RemoveOffset;
ZeroMethods = new ZeroMethods(copy.ZeroMethods);
InitialOffsets = new InitialOffsets(copy.InitialOffsets);
CalibrationId = copy.CalibrationId;
//43152
SensitivityInspection = copy.SensitivityInspection;
//43265
UsageCount = copy.UsageCount;
//43141
CalibrationNote = copy.CalibrationNote;
//this is downright silly, but because the linearization formula marks itself valid when it deserializes with data in it, we go and correct it here.
Records.Records[0].Poly.MarkValid(NonLinear);
}
public SensorCalDbRecord(IDataReader reader, int actualDbVersion)
{
try
{
CalibrationDate = Utility.GetDateTime(reader, "CalibrationDate", DateTime.MinValue);
LocalOnly = Utility.GetBool(reader, "LocalOnly", false);
SerialNumber = Utility.GetString(reader, "SerialNumber");
Username = Utility.GetString(reader, "Username");
Records = new CalibrationRecords(Utility.GetString(reader, "CalibrationRecords"));
NonLinear = Utility.GetBool(reader, "NonLinear");
IsProportional = Utility.GetBool(reader, "IsProportional");
ModifyDate = Utility.GetDateTime(reader, "ModifyDate", DateTime.MinValue);
CertificationDocuments = Utility.GetString(reader, "CertificationDocuments").Split(new[] { CultureInfo.InvariantCulture.TextInfo.ListSeparator }, StringSplitOptions.None).ToArray();
RemoveOffset = Utility.GetBool(reader, "RemoveOffset");
ZeroMethods = new ZeroMethods(Utility.GetString(reader, "ZeroMethod"));
InitialOffsets = new InitialOffsets(Utility.GetString(reader, "InitialOffset"));
if (actualDbVersion >= Constants.SENSOR_ASSEMBLY_DB_VERSION)
{
SensitivityInspection = (SensitivityInspectionType)Utility.GetInt(reader, "SensitivityInspection", 0);
CalibrationNote = Utility.GetString(reader, "CalibrationNote");
UsageCount = Utility.GetInt(reader, "UsageCount", 0);
}
CalibrationId = Utility.GetNullableInt(reader, "SensorCalibrationId");
//this is downright silly, but because the linearization formula marks itself valid when it deserializes with data in it, we go and correct it here.
Records.Records[0].Poly.MarkValid(NonLinear);
}
catch (Exception ex)
{
APILogger.Log("Failed to process Sensor Calibration record", ex);
}
}
}
}

View File

@@ -0,0 +1,38 @@
using System.Data;
using DTS.Common.Interface.Tags;
using DTS.Common.Interface.Sensors;
namespace DTS.Common.Classes.Sensors
{
public class SensorDbRecord : TagAwareBase, ISensorDbRecord
{
public override TagTypes TagType => TagTypes.SensorModels;
protected int _id = 0;
public int id
{
get => _id;
set => SetProperty(ref _id, value, "id");
}
protected short _sensorType = 0;
public short SensorType
{
get => _sensorType;
set => SetProperty(ref _sensorType, value, "SensorType");
}
protected string _serialNumber = string.Empty;
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
public SensorDbRecord(IDataReader reader)
{
id = Utility.GetInt(reader, "id", 0);
SensorType = Utility.GetShort(reader, "SensorType", 0);
SerialNumber = Utility.GetString(reader, "SerialNumber");
}
}
}

View File

@@ -0,0 +1,18 @@
using DTS.Common.Interface.Sensors.SensorsList;
namespace DTS.Common.Classes.Sensors.SensorsList
{
public class DragAndDropPayload
{
public IDragAndDropItem[] Items { get; }
public DragAndDropPayload(IDragAndDropItem[] items)
{
Items = items;
}
public const string FORMAT = "DTS.Common.Classes.Sensors.SensorsList.DragAndDropPayload";
public const string ALT_FORMAT = "ALT_DTS.Common.Classes.Sensors.SensorsList.DragAndDropPayload";
public const string CTRL_FORMAT = "CTRL_DTS.Common.Classes.Sensors.SensorsList.DragAndDropPayload";
}
}

View File

@@ -0,0 +1,316 @@
using DTS.Common.Base;
using DTS.Common.Enums;
using DTS.Common.Interface.Sensors;
using DTS.Common.Utilities.Logging;
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Linq;
namespace DTS.Common.Classes.Sensors
{
public class SquibDbRecord : BasePropertyChanged, ISquibDbRecord
{
private string _serialNumber = "";
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
private int _id = -1;
[Key]
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private bool _bypassCurrentFilter = false;
public bool BypassCurrentFilter
{
get => _bypassCurrentFilter;
set => SetProperty(ref _bypassCurrentFilter, value, "BypassCurrentFilter");
}
private bool _bypassVoltageFilter = false;
public bool BypassVoltageFilter
{
get => _bypassVoltageFilter;
set => SetProperty(ref _bypassVoltageFilter, value, "BypassVoltageFilter");
}
private double _delayMS = 0D;
[Column("DelayMS")]
public double DelayMs
{
get => _delayMS;
set => SetProperty(ref _delayMS, value, "DelayMs");
}
private double _durationMS = 10D;
[Column("DurationMS")]
public double DurationMs
{
get => _durationMS;
set => SetProperty(ref _durationMS, value, "DurationMs");
}
private SquibFireMode _fireMode = SquibFireMode.NONE;
public SquibFireMode FireMode
{
get => _fireMode;
set => SetProperty(ref _fireMode, value, "FireMode");
}
private string _isoCode = "";
[Required]
[StringLength(50)]
public string IsoCode
{
get => _isoCode;
set => SetProperty(ref _isoCode, value, "IsoCode");
}
private string _isoChannelName = "";
[Required]
[StringLength(255)]
public string IsoChannelName
{
get => _isoChannelName;
set => SetProperty(ref _isoChannelName, value, "IsoChannelName");
}
private string _userCode = "";
[Required]
[StringLength(50)]
public string UserCode
{
get => _userCode;
set => SetProperty(ref _userCode, value, "UserCode");
}
private string _userChannelName = "";
[Required]
[StringLength(255)]
public string UserChannelName
{
get => _userChannelName;
set => SetProperty(ref _userChannelName, value, "UserChannelName");
}
private SquibMeasurementType _squibMeasurementType = SquibMeasurementType.VOLTAGE;
public SquibMeasurementType MeasurementType
{
get => _squibMeasurementType;
set => SetProperty(ref _squibMeasurementType, value, "MeasurementType");
}
private double _squibOutputCurrent = 1.5D;
public double SquibOutputCurrent
{
get => _squibOutputCurrent;
set => SetProperty(ref _squibOutputCurrent, value, "SquibOutputCurrent");
}
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 bool _limitDuration = true;
public bool LimitDuration
{
get => _limitDuration;
set => SetProperty(ref _limitDuration, value, "LimitDuration");
}
private string _articleId = "";
[Required]
[StringLength(50)]
public string ArticleId
{
get => _articleId;
set => SetProperty(ref _articleId, value, "ArticleId");
}
private int _version = 1;
public int Version
{
get => _version;
set => SetProperty(ref _version, value, "Version");
}
private DateTime _lastModified = DateTime.MinValue;
[Column(TypeName = "datetime")]
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private string _lastModifiedBy = "";
[Required]
[StringLength(50)]
public string LastModifiedBy
{
get => _lastModifiedBy;
set => SetProperty(ref _lastModifiedBy, value, "LastModifiedBy");
}
private string _userValue1 = "";
[StringLength(255)]
public string UserValue1
{
get => _userValue1;
set => SetProperty(ref _userValue1, value, "UserValue1");
}
private string _userValue2 = "";
[StringLength(255)]
public string UserValue2
{
get => _userValue2;
set => SetProperty(ref _userValue2, value, "UserValue2");
}
private string _userValue3 = "";
[StringLength(255)]
public string UserValue3
{
get => _userValue3;
set => SetProperty(ref _userValue3, value, "UserValue3");
}
private byte[] _userTags = new byte[0];
public byte[] UserTags
{
get => _userTags;
set => SetProperty(ref _userTags, value, "UserTags");
}
private bool _doNotUse = false;
public bool DoNotUse
{
get => _doNotUse;
set => SetProperty(ref _doNotUse, value, "DoNotUse");
}
private bool _broken = false;
public bool Broken
{
get => _broken;
set => SetProperty(ref _broken, value, "Broken");
}
private bool _defineDelayInTest = false;
public bool DefineDelayInTest
{
get => _defineDelayInTest;
set => SetProperty(ref _defineDelayInTest, value, "DefineDelayInTest");
}
public SquibDbRecord(ISensorData copy, bool defineDelayInTest, byte[] tags)
{
Id = copy.DatabaseId;
IsoChannelName = copy.ISOChannelName;
UserCode = copy.UserCode;
UserChannelName = copy.UserChannelName;
Broken = copy.Broken;
DoNotUse = copy.DoNotUse;
Version = copy.Version;
SquibToleranceLow = copy.SquibToleranceLow;
SquibToleranceHigh = copy.SquibToleranceHigh;
SquibOutputCurrent = copy.SquibOutputCurrent;
SerialNumber = copy.SerialNumber;
MeasurementType = copy.SquibMeasurementType;
LimitDuration = copy.LimitDuration;
DefineDelayInTest = defineDelayInTest;
LastModifiedBy = copy.LastUpdatedBy;
LastModified = copy.LastModified;
IsoCode = copy.ISOCode;
FireMode = copy.SquibFireMode;
DurationMs = copy.SquibFireDurationMS;
DelayMs = copy.SquibFireDelayMS;
BypassVoltageFilter = copy.BypassVoltageFilter;
BypassCurrentFilter = copy.BypassCurrentFilter;
ArticleId = copy.EID;
UserValue1 = copy.UserValue1;
UserValue2 = copy.UserValue2;
UserValue3 = copy.UserValue3;
if (null == tags) { UserTags = null; }
else if (tags.Any())
{
var userTags = new byte[tags.Length];
Array.Copy(tags, userTags, tags.Length);
UserTags = userTags;
}
else { UserTags = new byte[0]; }
}
public SquibDbRecord() { }
public SquibDbRecord(ISquibDbRecord copy)
{
Id = copy.Id;
IsoChannelName = copy.IsoChannelName;
UserCode = copy.UserCode;
UserChannelName = copy.UserChannelName;
Broken = copy.Broken;
DoNotUse = copy.DoNotUse;
Version = copy.Version;
SquibToleranceLow = copy.SquibToleranceLow;
SquibToleranceHigh = copy.SquibToleranceHigh;
SquibOutputCurrent = copy.SquibOutputCurrent;
SerialNumber = copy.SerialNumber;
MeasurementType = copy.MeasurementType;
LimitDuration = copy.LimitDuration;
DefineDelayInTest = copy.DefineDelayInTest;
LastModifiedBy = copy.LastModifiedBy;
LastModified = copy.LastModified;
IsoCode = copy.IsoCode;
FireMode = copy.FireMode;
DurationMs = copy.DurationMs;
DelayMs = copy.DelayMs;
BypassVoltageFilter = copy.BypassVoltageFilter;
BypassCurrentFilter = copy.BypassCurrentFilter;
ArticleId = copy.ArticleId;
UserValue1 = copy.UserValue1;
//Comment = UserValue1;
UserValue2 = copy.UserValue2;
UserValue3 = copy.UserValue3;
if (null == copy.UserTags) { UserTags = null; }
else if (copy.UserTags.Any())
{
var userTags = new byte[copy.UserTags.Length];
Array.Copy(copy.UserTags, userTags, copy.UserTags.Length);
UserTags = userTags;
}
else { UserTags = new byte[0]; }
}
public SquibDbRecord(IDataReader reader)
{
try
{
Id = Utility.GetInt(reader, "Id", -1);
IsoChannelName = Utility.GetString(reader, "ISOChannelName", string.Empty);
UserCode = Utility.GetString(reader, "UserCode", string.Empty);
UserChannelName = Utility.GetString(reader, "UserChannelName", string.Empty);
Broken = Utility.GetBool(reader, "Broken", false);
DoNotUse = Utility.GetBool(reader, "DoNotUse", false);
Version = Utility.GetInt(reader, "Version", -1);
SquibToleranceLow = Utility.GetDouble(reader, "SquibToleranceLow", 0D);
SquibToleranceHigh = Utility.GetDouble(reader, "SquibToleranceHigh", 8D);
SquibOutputCurrent = Utility.GetDouble(reader, "SquibOutputCurrent", 1.5D);
SerialNumber = Utility.GetString(reader, "SerialNumber", string.Empty);
MeasurementType = (SquibMeasurementType)Utility.GetShort(reader, "MeasurementType");
LimitDuration = Utility.GetBool(reader, "LimitDuration");
DefineDelayInTest = Utility.GetBool(reader, "DefineDelayInTest");
LastModifiedBy = Utility.GetString(reader, "LastModifiedBy", string.Empty);
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
IsoCode = Utility.GetString(reader, "ISOCode", string.Empty);
FireMode = (SquibFireMode)Utility.GetShort(reader, "FireMode");
DurationMs = Utility.GetDouble(reader, "DurationMS", 0D);
DelayMs = Utility.GetDouble(reader, "DelayMS", 0D);
BypassVoltageFilter = Utility.GetBool(reader, "BypassVoltageFilter", false);
BypassCurrentFilter = Utility.GetBool(reader, "BypassCurrentFilter", false);
ArticleId = Utility.GetString(reader, "ArticleId", string.Empty);
UserValue1 = Utility.GetString(reader, "UserValue1");
//Comment = UserValue1;
UserValue2 = Utility.GetString(reader, "UserValue2", string.Empty);
UserValue3 = Utility.GetString(reader, "UserValue3", string.Empty);
var o = reader["UserTags"];
UserTags = DBNull.Value.Equals(o)
? new byte[0]
: (byte[])o;
}
catch (Exception ex)
{
APILogger.Log("Failed to process: ", ex);
}
}
}
}

View File

@@ -0,0 +1,98 @@
using DTS.Common.Enums;
using DTS.Common.Interface.Sensors;
using DTS.Common.Interface.Tags;
using DTS.Common.Utilities.Logging;
using System;
using System.Data;
namespace DTS.Common.Classes.Sensors
{
public class StreamInputRecord : TagAwareBase, IStreamInputRecord
{
public override TagTypes TagType => TagTypes.Sensors;
private int _id;
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private string _serialNumber;
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
private DateTime _lastModified;
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private string _lastUpdatedBy;
public string LastUpdatedBy
{
get => _lastUpdatedBy;
set => SetProperty(ref _lastUpdatedBy, value, "LastUpdatedBy");
}
private bool _doNotUse;
public bool DoNotUse
{
get => _doNotUse;
set => SetProperty(ref _doNotUse, value, "DoNotUse");
}
private bool _broken;
public bool Broken
{
get => _broken;
set => SetProperty(ref _broken, value, "Broken");
}
public const string DEFAULT_UDP_ADDRESS = "UDP://239.1.2.10:8400";
protected string _udpAddress = DEFAULT_UDP_ADDRESS;
public string StreamInUDPAddress
{
get => _udpAddress;
set => SetProperty(ref _udpAddress, value, "StreamInUDPAddress");
}
public StreamInputRecord(ISensorData sd)
{
try
{
Id = sd.DatabaseId;
SerialNumber = sd.SerialNumber;
StreamInUDPAddress = sd.StreamInUDPAddress;
Broken = sd.Broken;
DoNotUse = sd.DoNotUse;
LastModified = sd.LastModified;
LastUpdatedBy = sd.LastUpdatedBy;
}
catch (Exception ex)
{
APILogger.Log("Failed to process: ", ex);
}
}
public StreamInputRecord(IDataReader reader)
{
try
{
Id = Utility.GetInt(reader, "Id");
SerialNumber = Utility.GetString(reader, "SerialNumber");
StreamInUDPAddress = Utility.GetString(reader, "UDPAddress");
Broken = Utility.GetBool(reader, "Broken");
DoNotUse = Utility.GetBool(reader, "DoNotUse");
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastUpdatedBy = Utility.GetString(reader, "LastModifiedBy");
}
catch (Exception ex)
{
APILogger.Log("Failed to process: ", ex);
}
}
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading.Tasks;
namespace DTS.Common.Classes.Sensors.StreamOut
{
public class UDPStreamProfilePacket
{
public int TransHeader { get; set; } = 4;
public int TimeHeader { get; set; } = 24;
public int SecondTimeHeader { get; set; } = 0;
public int ChannelSpecificDataWord { get; set; } = 0;
public int PCMChannelSpecificDataWord { get; set; } = 0;
public int Id { get; set; } = 0;
public int SampleTime { get; set; } = 0;
public int PayloadFactor { get; set; } = 2;
public int Trailer { get; set; } = 0;
}
}

View File

@@ -0,0 +1,212 @@
using DTS.Common.Enums;
using DTS.Common.Interface.Sensors;
using DTS.Common.Interface.Tags;
using DTS.Common.Utilities.Logging;
using System;
using System.Collections.Generic;
using System.Data;
namespace DTS.Common.Classes.Sensors
{
public class StreamOutputRecord : TagAwareBase, IStreamOutputRecord
{
public override TagTypes TagType => TagTypes.Sensors;
private int _id;
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private string _serialNumber;
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
private DateTime _lastModified;
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private string _lastUpdatedBy;
public string LastUpdatedBy
{
get => _lastUpdatedBy;
set => SetProperty(ref _lastUpdatedBy, value, "LastUpdatedBy");
}
private bool _doNotUse;
public bool DoNotUse
{
get => _doNotUse;
set => SetProperty(ref _doNotUse, value, "DoNotUse");
}
private bool _broken;
public bool Broken
{
get => _broken;
set => SetProperty(ref _broken, value, "Broken");
}
protected UDPStreamProfile _udpProfile = DEFAULT_UDP_PROFILE;
public const UDPStreamProfile DEFAULT_UDP_PROFILE = UDPStreamProfile.CH10_ANALOG_2HDR; //supported on both S6A & TSRAIR
public UDPStreamProfile StreamOutUDPProfile
{
get => _udpProfile;
set => SetProperty(ref _udpProfile, value, "StreamOutUDPProfile");
}
public const string DEFAULT_UDP_ADDRESS = "UDP://239.1.2.10:8400";
protected string _udpAddress = DEFAULT_UDP_ADDRESS;
public string StreamOutUDPAddress
{
get => _udpAddress;
set => SetProperty(ref _udpAddress, value, "StreamOutUDPAddress");
}
public const ushort MINIMUM_STREAMOUT_TIMECHANNELID = 10;
public const ushort MAXIMUM_STREAMOUT_TIMECHANNELID = 100;
public const ushort DEFAULT_UDP_TIME_CHANNEL_ID = 1;
protected ushort _udpTimeChannelId = DEFAULT_UDP_TIME_CHANNEL_ID;
public ushort StreamOutUDPTimeChannelId
{
get => _udpTimeChannelId;
set => SetProperty(ref _udpTimeChannelId, value, "StreamOutUDPTimeChannelId");
}
public const ushort MINIMUM_STREAMOUT_DATACHANNELID = 10;
public const ushort MAXIMUM_STREAMOUT_DATACHANNELID = 100;
public const ushort DEFAULT_UDP_DATA_CHANNEL_ID = 3;
protected ushort _udpDataChannelId = DEFAULT_UDP_DATA_CHANNEL_ID;
public ushort StreamOutUDPDataChannelId
{
get => _udpDataChannelId;
set => SetProperty(ref _udpDataChannelId, value, "StreamOutUDPDataChannelId");
}
public const string DEFAULT_UDPTMNS_CONFIG = "(1,6,60,0,0,0,0,0)";
protected string _udpTmNSConfig = DEFAULT_UDPTMNS_CONFIG;
public string StreamOutUDPTmNSConfig
{
get => _udpTmNSConfig;
set => SetProperty(ref _udpTmNSConfig, value, "StreamOutUDPTmNSConfig");
}
public const ushort MINIMUM_STREAMOUT_TDP_INTERVAL_MS = 10;
public const ushort MAXIMUM_STREAMOUT_TDP_INTERVAL_MS = 1000;
public const ushort DEFAULT_IRIG_TIME_DATA_PACKET_INTERVAL_MS = 500;
protected ushort _irigTimeDataPacketIntervalMs = DEFAULT_IRIG_TIME_DATA_PACKET_INTERVAL_MS;
public const ushort MINIMUM_STREAMOUT_TMATS_INTERVAL_MS = ushort.MinValue;
public const ushort MAXIMUM_STREAMOUT_TMATS_INTERVAL_MS = ushort.MaxValue;
private ushort _streamOutTMATSIntervalMs = DEFAULT_TMATS_INTERVAL_MS;
/// <summary>
/// time in MS between sending 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 ushort StreamOutIRIGTimeDataPacketIntervalMs
{
get => _irigTimeDataPacketIntervalMs;
set => SetProperty(ref _irigTimeDataPacketIntervalMs, value, "StreamOutIRIGTimeDataPacketIntervalMs");
}
public StreamOutputRecord(ISensorData sd)
{
try
{
Id = sd.DatabaseId;
SerialNumber = sd.SerialNumber;
StreamOutUDPProfile = sd.StreamOutUDPProfile;
StreamOutUDPAddress = sd.StreamOutUDPAddress;
StreamOutUDPTimeChannelId = sd.StreamOutUDPTimeChannelId;
StreamOutUDPDataChannelId = sd.StreamOutUDPDataChannelId;
StreamOutUDPTmNSConfig = sd.StreamOutUDPTmNSConfig;
StreamOutIRIGTimeDataPacketIntervalMs = sd.StreamOutIRIGTimeDataPacketIntervalMs;
StreamOutTMATSIntervalMs = sd.StreamOutTMATSIntervalMs;
Broken = sd.Broken;
DoNotUse = sd.DoNotUse;
LastModified = sd.LastModified;
LastUpdatedBy = sd.LastUpdatedBy;
}
catch (Exception ex)
{
APILogger.Log("Failed to process: ", ex);
}
}
public StreamOutputRecord(IDataReader reader, int ClientDbVersion, int ConnectionDbVersion)
{
try
{
Id = Utility.GetInt(reader, "Id");
SerialNumber = Utility.GetString(reader, "SerialNumber");
StreamOutUDPProfile = (UDPStreamProfile)Enum.Parse(typeof(UDPStreamProfile),
Utility.GetString(reader, "StreamProfile"));
StreamOutUDPAddress = Utility.GetString(reader, "UDPAddress");
StreamOutUDPTimeChannelId = Utility.GetUShort(reader, "TimeChannelId");
StreamOutUDPDataChannelId = Utility.GetUShort(reader, "DataChannelId");
StreamOutUDPTmNSConfig = Utility.GetString(reader, "TmNSConfig");
StreamOutIRIGTimeDataPacketIntervalMs = Utility.GetUShort(reader, "IRIGTimeDataPacketIntervalMs");
Broken = Utility.GetBool(reader, "Broken");
DoNotUse = Utility.GetBool(reader, "DoNotUse");
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastUpdatedBy = Utility.GetString(reader, "LastModifiedBy");
//only try to retrieve this field if both client and db are high enough level
if (ClientDbVersion >= Constants.TMATS_INTERVAL_VERSION && ConnectionDbVersion >= Constants.TMATS_INTERVAL_VERSION)
{
StreamOutTMATSIntervalMs = Utility.GetUShort(reader, "TMATS_IntervalMS", StreamOutputRecord.DEFAULT_TMATS_INTERVAL_MS);
}
}
catch (Exception ex)
{
APILogger.Log("Failed to process: ", ex);
}
}
//28291 Reduce list of Stream profiles to choose from.
//Define this here so that it only needs to be changed in one place, if a change needs to be made in the future.
//30249 Add LTS behavior for case 30075 (ADC UART stream)
public static UDPStreamProfile[] AvailableUDPStreamProfiles(int ConnectionDbVersion, bool UseAdvancedStreamingProfiles)
{
var profiles = new List<UDPStreamProfile>();
if (UseAdvancedStreamingProfiles)
{
profiles.AddRange(
new UDPStreamProfile[]
{
UDPStreamProfile.CH10_ANALOG,
UDPStreamProfile.CH10_ANALOG_2HDR,
UDPStreamProfile.CH10_PCM128_MM,
UDPStreamProfile.CH10_PCM_128BIT_2HDR,
UDPStreamProfile.TMNS_PCM_STANDARD,
UDPStreamProfile.TMNS_PCM_SUPERCOM,
UDPStreamProfile.IENA_PTYPE_STREAM,
UDPStreamProfile.CH10_MANUAL_CONFIG
});
if (ConnectionDbVersion >= Constants.ADC_TO_UART_DB_VERSION)
{
profiles.Add(UDPStreamProfile.UART_STREAM);
}
}
else
{
// 31840 Basic / Advanced Streaming profiles
profiles.AddRange(
new UDPStreamProfile[]
{
UDPStreamProfile.CH10_ANALOG_2HDR,
UDPStreamProfile.CH10_PCM_128BIT_2HDR
});
}
return profiles.ToArray();
}
/// <summary>
/// the default interval between sending out tmats information while streaming
/// this is used if the value is not set or is null
/// http://manuscript.dts.local/f/cases/29987/Add-CG-DP-TMATS-interval-UI-support
/// </summary>
public const ushort DEFAULT_TMATS_INTERVAL_MS = 1000;
}
}

View File

@@ -0,0 +1,84 @@
using DTS.Common.Enums;
using DTS.Common.Interface.Sensors;
using DTS.Common.Interface.Tags;
using DTS.Common.Utilities.Logging;
using System;
using System.Data;
namespace DTS.Common.Classes.Sensors
{
public class ThermocouplerRecord : TagAwareBase, IThermocouplerRecord
{
public override TagTypes TagType => TagTypes.Sensors;
private int _id;
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private string _serialNumber;
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
private DateTime _lastModified;
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private string _lastUpdatedBy;
public string LastUpdatedBy
{
get => _lastUpdatedBy;
set => SetProperty(ref _lastUpdatedBy, value, "LastUpdatedBy");
}
private bool _doNotUse;
public bool DoNotUse
{
get => _doNotUse;
set => SetProperty(ref _doNotUse, value, "DoNotUse");
}
private bool _broken;
public bool Broken
{
get => _broken;
set => SetProperty(ref _broken, value, "Broken");
}
public ThermocouplerRecord(ISensorData sd)
{
try
{
Id = sd.DatabaseId;
SerialNumber = sd.SerialNumber;
Broken = sd.Broken;
DoNotUse = sd.DoNotUse;
LastModified = sd.LastModified;
LastUpdatedBy = sd.LastUpdatedBy;
}
catch (Exception ex)
{
APILogger.Log("Failed to process: ", ex);
}
}
public ThermocouplerRecord(IDataReader reader)
{
try
{
Id = Utility.GetInt(reader, "Id");
SerialNumber = Utility.GetString(reader, "SerialNumber");
Broken = Utility.GetBool(reader, "Broken");
DoNotUse = Utility.GetBool(reader, "DoNotUse");
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastUpdatedBy = Utility.GetString(reader, "LastModifiedBy");
}
catch (Exception ex)
{
APILogger.Log("Failed to process: ", ex);
}
}
}
}

View File

@@ -0,0 +1,137 @@
using DTS.Common.Base;
using DTS.Common.Enums;
using DTS.Common.Interface.Sensors;
using DTS.Common.Interface.Tags;
using DTS.Common.Utilities.Logging;
using System;
using System.Data;
using System.IO.Ports;
namespace DTS.Common.Classes.Sensors
{
public class UARTRecord : TagAwareBase, IUARTRecord
{
public override TagTypes TagType { get => TagTypes.Sensors; }
private int _id;
public int Id
{
get => _id;
set => SetProperty(ref _id, value, "Id");
}
private string _serialNumber;
public string SerialNumber
{
get => _serialNumber;
set => SetProperty(ref _serialNumber, value, "SerialNumber");
}
private uint _uartBaudRate = DTS.Common.Constant.EmbeddedSensors.BAUD_RATE_DEFAULT;
public uint UartBaudRate
{
get => _uartBaudRate;
set => _uartBaudRate = value;
}
public const uint UART_DATABITS_DEFAULT = 8;
private uint _uartDataBits = UART_DATABITS_DEFAULT;
public uint UartDataBits
{
get => _uartDataBits;
set => SetProperty(ref _uartDataBits, value, "UartDataBits");
}
private StopBits _uartStopBits = StopBits.None;
public const StopBits UART_STOPBITS_DEFAULT = StopBits.None;
public StopBits UartStopBits
{
get => _uartStopBits;
set => _uartStopBits = value;
}
public const UartDataFormat UART_DATAFORMAT_DEFAULT = UartDataFormat.Binary;
public const Handshake UART_FLOWCONTROL_DEFAULT = Handshake.None;
protected Handshake _flowControl = Handshake.None;
public Handshake UartFlowControl
{
get => _flowControl;
set => SetProperty(ref _flowControl, value, "UartFlowControl");
}
private UartDataFormat _uartDataFormat = UART_DATAFORMAT_DEFAULT;
public UartDataFormat UartDataFormat
{
get => _uartDataFormat;
set => SetProperty(ref _uartDataFormat, value, "UartDataFormat");
}
private DateTime _lastModified;
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private string _lastUpdatedBy;
public string LastUpdatedBy
{
get => _lastUpdatedBy;
set => SetProperty(ref _lastUpdatedBy, value, "LastUpdatedBy");
}
private bool _doNotUse;
public bool DoNotUse
{
get => _doNotUse;
set => SetProperty(ref _doNotUse, value, "DoNotUse");
}
private bool _broken;
public bool Broken
{
get => _broken;
set => SetProperty(ref _broken, value, "Broken");
}
public const Parity UART_PARITY_DEFAULT = Parity.None;
protected Parity _parity = Parity.None;
public Parity UartParity
{
get => _parity;
set => SetProperty(ref _parity, value, "UartParity");
}
public UARTRecord(ISensorData sensor)
{
Id = sensor.DatabaseId;
SerialNumber = sensor.SerialNumber;
UartBaudRate = sensor.UartBaudRate;
UartDataBits = sensor.UartDataBits;
UartStopBits = sensor.UartStopBits;
UartParity = sensor.UartParity;
UartFlowControl = sensor.UartFlowControl;
UartDataFormat = sensor.UartDataFormat;
Broken = sensor.Broken;
DoNotUse = sensor.DoNotUse;
LastModified = sensor.LastModified;
LastUpdatedBy = sensor.LastUpdatedBy;
}
public UARTRecord(IDataReader reader)
{
try
{
Id = Utility.GetInt(reader, "Id");
SerialNumber = Utility.GetString(reader, "SerialNumber");
UartBaudRate = Utility.GetUInt(reader, "BaudRate");
UartDataBits = Utility.GetUInt(reader, "DataBits");
UartStopBits = (StopBits)Enum.Parse(typeof(StopBits), Utility.GetString(reader, "StopBits"));
UartParity = (Parity)Enum.Parse(typeof(Parity), Utility.GetString(reader, "Parity"));
UartFlowControl = (Handshake)Enum.Parse(typeof(Handshake), Utility.GetString(reader, "FlowControl"));
UartDataFormat = (UartDataFormat)Enum.Parse(typeof(UartDataFormat), Utility.GetString(reader, "DataFormat"));
Broken = Utility.GetBool(reader, "Broken");
DoNotUse = Utility.GetBool(reader, "DoNotUse");
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastUpdatedBy = Utility.GetString(reader, "LastModifiedBy");
}
catch (Exception ex)
{
APILogger.Log("Failed to process: ", ex);
}
}
}
}

View File

@@ -0,0 +1,304 @@
using System;
using System.Text;
using System.Xml.Linq;
using System.ComponentModel;
using DTS.Common.Utilities.Logging;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.Sensors;
using System.Collections.Generic;
namespace DTS.Common.Classes.Sensors
{
public class ZeroMethod : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, String propertyName = null)
{
if (Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public override int GetHashCode()
{
return Method.GetHashCode() + Start.GetHashCode() + End.GetHashCode();
}
public ZeroMethodType Method { get; set; } = SensorConstants.DefaultZeroMethodType; // FB12764: Belt-and-suspenders, fetch default from SensorConstants
public double Start { get; set; } = SensorConstants.DefaultZeroMethodStart; // FB12764: Belt-and-suspenders, fetch default from SensorConstants
public double End { get; set; } = SensorConstants.DefaultZeroMethodEnd; // FB12764: Belt-and-suspenders, fetch default from SensorConstants
#region Tags
internal const string ZERO_METHOD_TAG = "ZeroMethod";
internal const string METHOD_TAG = "Method";
internal const string START_TAG = "Start";
internal const string END_TAG = "End";
#endregion
public ZeroMethod(ZeroMethodType zm, double start, double end)
{
Method = zm;
Start = start;
End = end;
}
public ZeroMethod(string zm, System.Globalization.CultureInfo culture)
{
Initialize(zm, culture);
}
public ZeroMethod(string zm)
{
Initialize(zm, System.Globalization.CultureInfo.InvariantCulture);
}
/// <summary>
/// do a deep copy
/// </summary>
/// <param name="copy"></param>
public ZeroMethod(ZeroMethod copy)
{
Method = copy.Method;
Start = copy.Start;
End = copy.End;
}
private void Initialize(string zm, System.Globalization.CultureInfo culture)
{
var tokens = zm.Split(',');
if (tokens.Length < 3) { return; }
Start = Convert.ToDouble(tokens[1], culture);
End = Convert.ToDouble(tokens[2], culture);
if (tokens[0].Contains("PreCalZero"))
{
Method = ZeroMethodType.UsePreEventDiagnosticsZero;
}
else
{
Method = (ZeroMethodType)
Enum.Parse(typeof(ZeroMethodType), tokens[0]);
}
}
public string ToDbString()
{
return $"{Method.ToString()},{Start},{End}";
}
private readonly string _tableName;
public ZeroMethod(XElement elem, string prefix, string tblName, string id)
{
_tableName = tblName;
XElement inner;
try
{
inner = elem.Element(mkTag(prefix));
}
catch (ArgumentNullException)
{
if (!string.IsNullOrEmpty(id))
{
throw new Exception($"{_tableName}: Can't find tag {prefix + "-" + ZERO_METHOD_TAG} for entry {id}");
}
throw new Exception($"{_tableName}: Can't find tag {prefix + "-" + ZERO_METHOD_TAG} in file");
}
try
{
// this is a special case to remain compatible with older TDM
// I moved this to avoid the exception
// 6/8/2010 - dtm
if (inner.Value == "UsePreCalZero")
{
Method = ZeroMethodType.UsePreEventDiagnosticsZero;
}
else if (inner.Value == ZeroMethodType.UsePreEventDiagnosticsZero.ToString())
{
inner.Value = "UsePreCalZero";
Method = ZeroMethodType.UsePreEventDiagnosticsZero;
}
else
{
Method = (ZeroMethodType)Enum.Parse(typeof(ZeroMethodType), inner.Value);
}
}
catch (ArgumentException ex)
{
APILogger.Log(ex);
throw;
}
Start = double.Parse(inner.Attribute(START_TAG).Value, System.Globalization.CultureInfo.InvariantCulture);
End = double.Parse(inner.Attribute(END_TAG).Value, System.Globalization.CultureInfo.InvariantCulture);
}
internal XElement ToXElement(string prefix)
{
string value;
switch (Method)
{
case ZeroMethodType.UsePreEventDiagnosticsZero:
value = "UsePreCalZero";
break;
default:
value = Method.ToString();
break;
}
var element = new XElement(mkTag(prefix), value);
element.SetAttributeValue(START_TAG, Start);
element.SetAttributeValue(END_TAG, End);
return element;
}
internal void Update(XElement elem, string prefix)
{
elem.SetElementValue(mkTag(prefix), Method.ToString());
var element = elem.Element(mkTag(prefix));
element.SetAttributeValue(START_TAG, Start);
element.SetAttributeValue(END_TAG, End);
}
internal static string mkTag(string prefix)
{
return prefix + "-" + ZERO_METHOD_TAG;
}
public string ToSerializeString()
{
return $"{Method.ToString()},{Start.ToString(System.Globalization.CultureInfo.InvariantCulture)},{End.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public string ToDisplayString(string averageOverTimeFormatString, string diagnosticLevelFormatString, string absoluteZeroFormatString)
{
var sb = new StringBuilder();
switch (Method)
{
case ZeroMethodType.AverageOverTime:
sb.AppendFormat("{0} from {1} to {2}", averageOverTimeFormatString, Start, End);
break;
case ZeroMethodType.UsePreEventDiagnosticsZero:
sb.AppendFormat("{0}", diagnosticLevelFormatString);
break;
case ZeroMethodType.None:
sb.AppendFormat("{0}", absoluteZeroFormatString);
break;
}
return sb.ToString();
}
public override bool Equals(object obj)
{
if (obj is ZeroMethod zm)
{
return zm.Method == Method && zm.Start == Start && zm.End == End;
}
return base.Equals(obj);
}
}
public class ZeroMethods : IZeroMethods
{
public ZeroMethod[] Methods { get; set; } = new ZeroMethod[] { };
public ZeroMethods(ZeroMethods copy) : this(copy.Methods)
{
}
public ZeroMethods(ZeroMethod[] copyMethods)
{
ZeroMethod[] methods = new ZeroMethod[copyMethods.Length];
for (int i = 0; i < copyMethods.Length; i++)
{
methods[i] = new ZeroMethod(copyMethods[i]);
}
Methods = methods;
}
public ZeroMethods()
{
Methods = new ZeroMethod[] { };
}
public ZeroMethods(string methods)
{
FromSerializedString(methods);
}
public ZeroMethods(ZeroMethod startingMethod)
{
Methods = new ZeroMethod[] { startingMethod };
}
public override bool Equals(object obj)
{
if (obj is ZeroMethods r)
{
if (r.Methods.Length != Methods.Length) { return false; }
for (int i = 0; i < r.Methods.Length; i++)
{
if (!r.Methods[i].Equals(Methods[i])) { return false; }
}
return true;
}
return base.Equals(obj);
}
public void FromSerializedString(string s)
{
string[] tokens = s.Split(new string[] { MySeparator }, StringSplitOptions.None);
for (int i = 0; i < tokens.Length; i++) { tokens[i] = tokens[i].Replace(MySeparatorBackup, MySeparator); }
List<ZeroMethod> methods = new List<ZeroMethod>();
foreach (string token in tokens)
{
methods.Add(new ZeroMethod(token));
}
Methods = methods.ToArray();
}
private const string MySeparator = "__x__";
private const string MySeparatorBackup = "___xx___";
public string ToSerializedString()
{
List<string> methods = new List<string>();
foreach (var r in Methods) { methods.Add(r.ToSerializeString()); }
for (int i = 0; i < methods.Count; i++)
{
System.Diagnostics.Trace.Assert(!methods[i].Contains(MySeparatorBackup));
methods[i] = methods[i].Replace(MySeparator, MySeparatorBackup);
}
return string.Join(MySeparator, methods.ToArray());
}
public string ToDisplayString(string averageOverTimeFormatString, string diagnosticLevelFormatString, string absoluteZeroFormatString)
{
StringBuilder sb = new StringBuilder();
/*foreach (var r in Methods)
{
if (currentMethod > 1) { sb.AppendLine(); }
sb.AppendFormat("{0}: {1}", currentMethod++, r.ToDisplayString(sc));
}*/
for (int i = 0; i < Methods.Length; i++)
{
if (i > 0) { sb.AppendLine(); }
string s = Methods[i].ToDisplayString(averageOverTimeFormatString, diagnosticLevelFormatString, absoluteZeroFormatString);
if (!string.IsNullOrEmpty(s))
{
sb.Append(s);
}
}
return sb.ToString();
}
public override string ToString()
{
return ToDisplayString(Strings.Strings.SensorFields_InitialOffset_AverageOverTimeFormat, Strings.Strings.SensorFields_InitialOffset_DiagnosticLevelFormat,
Strings.Strings.SensorFields_InitialOffset_AbsoluteZeroFormat);
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
namespace DTS.Common.Classes.Sensors
{
/// <summary>
/// public helper class for ZeroRefence in SIFs, which is serialized to an int
/// </summary>
public class ZeroRef
{
public enum ZeroType
{
AverageOverTime,
UsePreEventDiagnostics,
UseZeroMv
}
public ZeroType ZeroMethod { get; }
public ZeroRef(string zeroref)
{
switch (zeroref)
{
case "0":
ZeroMethod = ZeroType.AverageOverTime;
break;
case "1":
ZeroMethod = ZeroType.UsePreEventDiagnostics;
break;
case "2":
ZeroMethod = ZeroType.UseZeroMv;
break;
default:
throw new NotSupportedException("TDAS::ZeroRef Invalid ZeroRef " + zeroref);
}
}
public ZeroRef(ZeroType type) { ZeroMethod = type; }
public override string ToString()
{
switch (ZeroMethod)
{
case ZeroType.AverageOverTime:
return "0";
case ZeroType.UsePreEventDiagnostics:
return "1";
case ZeroType.UseZeroMv:
return "2";
default:
throw new NotSupportedException("TDAS::ZeroRef Invalid ZeroRef " + ZeroMethod);
}
}
}
}

View File

@@ -0,0 +1,117 @@
using DTS.Common.Utilities.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace DTS.Common.Classes
{
/// <summary>
/// This class represents work requested of the services framework
/// </summary>
public class ServiceCall
{
public bool Started { get; set; } = false;
/// <summary>
/// the work to be done when service call is made
/// </summary>
public Action WorkAction { get; set; }
/// <summary>
/// indicates the service call is complete
/// </summary>
public void MarkDone()
{
ServiceQueue.MarkFinished(this);
}
public string Name { get; set; }
public ServiceCall(string name)
{
Name = name;
}
}
/// <summary>
/// this class handles calls of the services framework by doing a little managing of who gets to run and when
/// </summary>
public class ServiceQueue
{
/// <summary>
/// just a lock to keep resource access thread safe
/// </summary>
private static readonly object QueueLock = new object();
/// <summary>
/// this is sort of a Queue, actions are enqueued when the are instantiated,
/// but using a list allows us to re-order then when needed and to remove items that are no longer needed and haven't been
/// started yet
/// </summary>
private readonly List<ServiceCall> ServiceCalls = new List<ServiceCall>();
/// <summary>
/// the singleton/the instance of the queue
/// </summary>
private static ServiceQueue _serviceQueue = new ServiceQueue();
/// <summary>
/// adds a new item for the services framework to handle
/// </summary>
/// <param name="call"></param>
public static void Enqueue(ServiceCall call)
{
lock (QueueLock)
{
//adds work item to the queue
_serviceQueue.ServiceCalls.Add(call);
//start the item if it's the only item in the queue
if (1 == _serviceQueue.ServiceCalls.Count)
{
StartWork();
}
}
}
/// <summary>
/// starts a call into the services framework
/// </summary>
private static void StartWork()
{
lock (QueueLock)
{
//if there's any calls in the queue, launch the first
if (_serviceQueue.ServiceCalls.Any())
{
var work = _serviceQueue.ServiceCalls[0];
//to prevent multiple startworks from starting the same work, just make sure it's not started
if (work.Started) { return; }
work.Started = true;
Task.Run(() => { work.WorkAction(); });
}
}
}
/// <summary>
/// marks a servicecall as finished, if it's the current work item the next work item will be started if any
/// </summary>
/// <param name="call"></param>
public static void MarkFinished(ServiceCall call)
{
lock (QueueLock)
{
if (!_serviceQueue.ServiceCalls.Any() || !_serviceQueue.ServiceCalls.Contains(call))
{
return;
}
if (_serviceQueue.ServiceCalls[0] != call)
{
//it wasn't being actively worked on, just remove
_serviceQueue.ServiceCalls.Remove(call);
return;
}
//this was the current work item, so we are free to start a new item
_serviceQueue.ServiceCalls.RemoveAt(0);
if (_serviceQueue.ServiceCalls.Any())
{
StartWork();
}
}
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
namespace DTS.Common.Classes
{
/// <summary>
/// This is the generic for singletons.
/// </summary>
/// <typeparam name="T">Type of derived Singleton object (i.e. class MySingletone: Singleton&lt;MySingleton&gt;).</typeparam>
public class Singleton<T> where T : new()
{
/// <summary>
/// This is a protected constructor.
/// </summary>
protected Singleton()
{
if (!ReferenceEquals(Instance, null))
throw new InvalidOperationException("You have tried to create a new singleton class where you should have instanced it. Replace your \"new class()\" with \"class.Instance\"");
}
/// <summary>
/// Gets the singleton instance of type T.
/// </summary>
public static T Instance
{
get
{
if (SingletonCreator.exception != null)
throw SingletonCreator.exception;
return SingletonCreator.instance;
}
}
/// <summary>
/// Creates the singleton instance of type T.
/// </summary>
// ReSharper disable once ClassNeverInstantiated.Local
private class SingletonCreator
{
internal static readonly T instance;
internal static readonly Exception exception;
/// <summary>
/// Creates the singleton instance of type T.
/// </summary>
static SingletonCreator()
{
try
{
instance = new T();
}
catch (Exception ex)
{
exception = ex.InnerException ?? ex;
Console.WriteLine(@"Singleton: {0}", exception);
}
}
}
}
}

View File

@@ -0,0 +1,16 @@
using System.Windows;
using System.Windows.Media;
using DTS.Common.Base;
namespace DTS.Common.Classes
{
public class StatusAndProgressBarEventArgs
{
public Color StatusColor { get; set; }
public string StatusText { get; set; }
public double ProgressValue { get; set; }
public Visibility ProgressBarVisibility { get; set; }
public IBaseViewModel Requester { get; set; }
public string ErrorText { get; set; }
}
}

View File

@@ -0,0 +1,363 @@
using DTS.Common.Enums;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Interface.DASFactory.Config;
using System;
namespace DTS.Common.Classes.TMAT
{
/// <summary>
/// these are all the patterns that represent global keys
/// </summary>
public enum TMTGlobalKeys
{
[TMTKey("{NAME OF PROGRAM}")] NameOfProgram,
[TMTKey("{TEST ID}")] TestId,
[TMTKey("{DAS SERIAL NUMBER}")] DASSerialNumber,
[TMTKey("{DAS INDEX}")] DASIndex,
[TMTKey("{DAS SAMPLE RATE}")] DASSampleRate,
[TMTKey("{TEST TIMESTAMP}")] TestTimeStamp,
[TMTKey("{DAS BIT RATE}")] DASBitRate,
[TMTKey("{STREAM TIME FORMAT}")] StreamTimeFormat,
//FB 26736 Keys for time & data channel Id
[TMTKey("{UDP STREAM TIME CHANNEL ID}")] UdpStreamTimeChannelId,
[TMTKey("{UDP STREAM DATA CHANNEL ID}")] UdpStreamDataChannelId,
//FB 43761
[TMTKey("{UDP STREAM UART CHANNEL ID}")] UdpStreamUartChannelId,
[TMTKey("{UDP STREAM UART CHANNEL ID ENABLED}")] UdpStreamUartChannelIdEnabled,
//FB 29996 Key for file creation date
[TMTKey("{CREATE DATE}")] CreateDate,
//http://manuscript.dts.local/f/cases/37929/Implement-TSRAIR-module-on-off-selection-via-Max-Slice-Enable-system-attribute
[TMTKey("{NUMBER OF STREAMED CHANNELS}")] NumberOfStreamedChannels,
[TMTKey("{NUMBER OF CHANNELS PLUS TIME}")] NumberOfChannelsPlusTime,
[TMTKey("{NUMBER OF BITS PER MINOR FRAME}")] NumberOfBitsPerMinorFrame
}
/// <summary>
/// these are all the patterns that represent channel keys when channels are all part of 1 template
/// </summary>
public enum TMTChannelKeys
{
[TMTKey("{{CHANNEL {0} HARDWARE CHANNEL NUMBER}}")] HardwareChannelNumber,
[TMTKey("{{CHANNEL {0} NAME}}")] ChannelName,
[TMTKey("{{CHANNEL {0} COUPLING MODE}}")] CouplingMode,
[TMTKey("{{CHANNEL {0} BRIDGE RESISTANCE}}")] BridgeResistance,
[TMTKey("{{CHANNEL {0} AAF}}")] AAF,
[TMTKey("{{CHANNEL {0} OFFSET mV}}")] OffsetMV,
[TMTKey("{{CHANNEL {0} INPUT RANGE}}")] InputRangeMV,
[TMTKey("{{CHANNEL {0} MAX RANGE EU}}")] MaxRangeEU,
[TMTKey("{{CHANNEL {0} MIN RANGE EU}}")] MinRangeEU,
[TMTKey("{{CHANNEL {0} EU}}")] EU,
[TMTKey("{{CHANNEL {0} SCALEFACTOR EU}}")] ScaleFactorEU,
[TMTKey("{{CHANNEL {0} OFFSET EU}}")] OffsetEU,
}
/// <summary>
/// these are patterns for channel keys when channels are split into a separate template
/// </summary>
public enum TMTChannelKeysEx
{
[TMTKey("{CHANNEL NUMBER}")]ChannelNumber,
[TMTKey("{CHANNEL NAME}")]ChannelName,
[TMTKey("{CHANNEL OFFSET EU}")]ChannelOffsetEU,
[TMTKey("{CHANNEL SCALEFACTOR EU}")]ChannelScaleFactorEU,
[TMTKey("{CHANNEL EU}")]ChannelEU,
[TMTKey("{CHANNEL MAX RANGE EU}")]ChannelMaxRangeEU,
[TMTKey("{CHANNEL MIN RANGE EU}")]ChannelMinRangeEU,
[TMTKey("{BYTE FORMAT}")]ByteFormat,
[TMTKey("{BYTE FORMAT2}")]ByteFormat2,
[TMTKey("{CHANNEL MIDPOINT}")]ChannelMidPoint
}
/// <summary>
/// Helper attribute, allows us to associate patterns to enums to make processing file easier
/// </summary>
[System.AttributeUsage(System.AttributeTargets.Field)]
public class TMTKey : System.Attribute
{
/// <summary>
/// the pattern to look for in a line to replace
/// </summary>
public string Key { get; set; }
public TMTKey(string key)
{
Key = key;
}
/// <summary>
/// returns the pattern to look for in a line for a given property
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public static string GetKey(TMTGlobalKeys o)
{
var mi = o.GetType().GetMember(o.ToString());
if (mi.Length <= 0) return string.Empty;
return GetCustomAttribute(mi[0], typeof(TMTKey)) is TMTKey attr ? attr.Key : string.Empty;
}
/// <summary>
/// returns the pattern to look for in a line for a given property
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public static string GetKey(TMTChannelKeysEx o)
{
var mi = o.GetType().GetMember(o.ToString());
if (mi.Length <= 0) return string.Empty;
return GetCustomAttribute(mi[0], typeof(TMTKey)) is TMTKey attr ? attr.Key : string.Empty;
}
/// <summary>
/// returns the pattern to look for in a line for a given channel property
/// </summary>
/// <param name="o"></param>
/// <param name="channelNumber"></param>
/// <returns></returns>
public static string GetKey(TMTChannelKeys o, int channelNumber)
{
var mi = o.GetType().GetMember(o.ToString());
if (mi.Length <= 0) return string.Empty;
if (GetCustomAttribute(mi[0], typeof(TMTKey)) is TMTKey attr)
{
return string.Format(attr.Key, channelNumber);
}
else
{
return string.Empty;
}
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S101:Types should be named in Acronym", Justification = "<Pending>")]
public interface ITMTTemplate
{
/// <summary>
/// updates the fields in the file with a given value
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
void UpdateValue(TMTChannelKeysEx key, string value, int channelNumber);
/// <summary>
/// updates the fields in the file with a given value
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
void UpdateValue(TMTGlobalKeys key, string value);
/// <summary>
/// updates the files in the file with the given value
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="channelNumber"></param>
void UpdateValue(TMTChannelKeys key, string value, int channelNumber);
/// <summary>
/// returns all lines in the TMT file
/// </summary>
/// <returns></returns>
string[] GetAllLines();
}
public abstract class TmtBase : ITMTTemplate
{
/// <summary>
/// this is the max length of the channel name in a TMT file,
/// this was done in an effort to keep TMT file length below 4k bytes
/// 2019-10-10 - DTM increased this to 200 as TMT file length was increased to 16k
/// </summary>
private const int TMT_MAX_CHANNEL_LENGTH = 200;
/// <summary>
/// does the work to ensure string is of MAX_LENGTH or shorter
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string TMT_LimitString(string s)
{
return s.Substring(0, Math.Min(s.Length, TMT_MAX_CHANNEL_LENGTH));
}
private static string ScaleFactorOrOffsetToString(double d)
{
return $"{d:0.0##########}";//F11, but strip trailing zeros
}
/// <summary>
/// updates the given field in the template with a value
/// </summary>
public static void UpdateChannelField(TMTChannelKeysEx key, ITMTTemplate template, int channelIndex,
float [] ranges, double minEU, double maxEU, string eu, float [] scaleFactors, double adcToEUScalingFactor,
string channelName2, string offsetEU, bool bSigned)
{
switch (key)
{
case TMTChannelKeysEx.ChannelNumber:
template.UpdateValue(key, $"{1 + channelIndex}", channelIndex);
break;
case TMTChannelKeysEx.ChannelName:
template.UpdateValue(key, TMT_LimitString(channelName2), channelIndex);
break;
case TMTChannelKeysEx.ChannelOffsetEU:
template.UpdateValue(key, TMT_LimitString(offsetEU), channelIndex);
break;
case TMTChannelKeysEx.ChannelScaleFactorEU:
if (scaleFactors != null)
{
template.UpdateValue(key, ScaleFactorOrOffsetToString(scaleFactors[channelIndex]), channelIndex);
}
else
{
template.UpdateValue(key, RunTestVariables.MaskEUMetaData ? "1" : ScaleFactorOrOffsetToString(adcToEUScalingFactor), channelIndex);
}
break;
case TMTChannelKeysEx.ByteFormat:
template.UpdateValue(key, bSigned?"TWO":"OFF", channelIndex);
break;
case TMTChannelKeysEx.ByteFormat2:
template.UpdateValue(key, bSigned?"2":"B", channelIndex);
break;
case TMTChannelKeysEx.ChannelMidPoint:
template.UpdateValue(key, bSigned?"0":"2500", channelIndex);
break;
case TMTChannelKeysEx.ChannelEU:
template.UpdateValue(key,
RunTestVariables.MaskEUMetaData ? "---" : eu?.Trim() ?? "", channelIndex);
break;
case TMTChannelKeysEx.ChannelMaxRangeEU:
{
if ( ranges != null)
{
template.UpdateValue(key, ranges[channelIndex].ToString("F0"), channelIndex);
}
else { template.UpdateValue(key, RunTestVariables.MaskEUMetaData ? "1" : maxEU.ToString("F0"), channelIndex); }
}
break;
case TMTChannelKeysEx.ChannelMinRangeEU:
{
if (ranges != null)
{
template.UpdateValue(key, (-1 * ranges[channelIndex]).ToString("F0"), channelIndex);
}
else
{
template.UpdateValue(key, RunTestVariables.MaskEUMetaData ? "1" :
minEU.ToString("F0"), channelIndex);
}
}
break;
}
}
public static void UpdateGlobalField(IDASCommunication das, TMTGlobalKeys key, ITMTTemplate template,
IConfigurationData ConfigData,
String serialNumber,
ushort? timeChannelId,
ushort? dataChannelId,
ushort? uartChannelId,
int dasIndex,
int bitsPerFrame)
{
switch (key)
{
case TMTGlobalKeys.NameOfProgram:
template.UpdateValue(key,
TMT_LimitString(System.Reflection.Assembly.GetExecutingAssembly().GetName().Name));
break;
case TMTGlobalKeys.TestId:
template.UpdateValue(key, TMT_LimitString(ConfigData.TestID));
break;
case TMTGlobalKeys.CreateDate:
//FB 29996 used the same date format from the template
template.UpdateValue(key, DateTime.Now.ToString("MM-dd-yyyy"));
break;
case TMTGlobalKeys.DASSerialNumber:
template.UpdateValue(key, serialNumber);
break;
// FB 26736 replace time & data channel Ids in template
case TMTGlobalKeys.UdpStreamDataChannelId:
if (dataChannelId.HasValue)
{
template.UpdateValue(key, dataChannelId.Value.ToString());
}
break;
case TMTGlobalKeys.UdpStreamTimeChannelId:
if (timeChannelId.HasValue)
{
template.UpdateValue(key, timeChannelId.Value.ToString());
}
break;
//FB 43761 update tmat file with uart channel id & enable/disable T/F
case TMTGlobalKeys.UdpStreamUartChannelId:
if (uartChannelId.HasValue)
{
template.UpdateValue(key, uartChannelId.Value.ToString());
}
break;
case TMTGlobalKeys.UdpStreamUartChannelIdEnabled:
if (uartChannelId.HasValue)
{
template.UpdateValue(key, uartChannelId.Value > 0 ? "T" : "F");
}
else
{
template.UpdateValue(key, "F");
}
break;
case TMTGlobalKeys.DASIndex:
template.UpdateValue(key, dasIndex.ToString());
break;
case TMTGlobalKeys.DASSampleRate:
template.UpdateValue(key, ConfigData.Modules[0].SampleRateHz.ToString());
break;
case TMTGlobalKeys.DASBitRate:
template.UpdateValue(key,
(ConfigData.Modules[0].SampleRateHz * bitsPerFrame).ToString());
break;
case TMTGlobalKeys.StreamTimeFormat:
// FB15388 Add line "R-1\TTF-1:{TIME FORMAT};" to detail either time format 1 or 2
// FB 30035 Get stream time format from StreamOut module
var streamOutModule = Array.Find(ConfigData.Modules, m => m.ModuleType() == DFConstantsAndEnums.ModuleType.StreamOut);
if (streamOutModule != null)
{
template.UpdateValue(key, streamOutModule.StreamProfile.ToString().Contains(Constants.UDP_STREAM_CH10_TF2) ? "2" : "1");
}
break;
case TMTGlobalKeys.TestTimeStamp:
var now = DateTime.Now;
var timeStamp =
$"{now.Month:00}-{now.Day:00}-{now.Year:0000}-{now.Hour:00}-{now.Minute:00}-{now.Second:00}";
template.UpdateValue(key, timeStamp);
break;
case TMTGlobalKeys.NumberOfStreamedChannels: template.UpdateValue(key, GetNumberOfStreamedChannels(das).ToString()); break;
case TMTGlobalKeys.NumberOfChannelsPlusTime: template.UpdateValue(key, (1 + GetNumberOfStreamedChannels(das)).ToString()); break;
case TMTGlobalKeys.NumberOfBitsPerMinorFrame: template.UpdateValue(key, (32 + 16 * GetNumberOfStreamedChannels(das)).ToString()); break;
}
}
public static int GetNumberOfStreamedChannels(IDASCommunication das)
{
if (das is IDASReconfigure reconfigure)
{
if (das.GetHardwareType() == Enums.Hardware.HardwareTypes.SLICE6_AIR_TC)
{
return 24;
}
return GetNumberOfStreamedChannelsReconfigurable(das);
}
else { return 6; }
}
private static int GetNumberOfStreamedChannelsReconfigurable(IDASCommunication das)
{
//for now the TSR AIR is the only reconfigurable streaming devices? we may need to fix this in the future
switch (das.DASInfo.Modules.Length)
{
case 3: return 3; //TSR AIR Lowg only (low g + stream output + UART)
case 4: return 6; //TSR AIR LowG & High G (low g + high g + stream output + UART)
case 5: return 9; //TSR AIR LowG, HighG, ARS
default: return 18; //ALL
}
}
public abstract void UpdateValue(TMTChannelKeysEx key, string value, int channelNumber);
public abstract void UpdateValue(TMTGlobalKeys key, string value);
public abstract void UpdateValue(TMTChannelKeys key, string value, int channelNumber);
public abstract string[] GetAllLines();
}
}

View File

@@ -0,0 +1,85 @@
using System.Collections.Generic;
namespace DTS.Common.Classes.TMAT
{
/// <summary>
/// this class handles a TMATS template in only one file
/// </summary>
public class TmtSingleFile : TmtBase
{
/// <summary>
/// reads all lines from the file in the given location and prepare to update values
/// </summary>
/// <param name="templateLocation"></param>
public TmtSingleFile(string templateLocation)
{
if (System.IO.File.Exists(templateLocation))
{
_allLines.AddRange(System.IO.File.ReadAllLines(templateLocation));
}
}
/// <summary>
/// updates the files in the file with a given value
/// </summary>
public override void UpdateValue(TMTChannelKeysEx key, string value, int channelNumber)
{
var pattern = TMTKey.GetKey(key);
for (var i = 0; i < _allLines.Count; i++)
{
if (_allLines[i].Contains(pattern))
{
_allLines[i] = _allLines[i].Replace(pattern, value);
}
}
}
/// <summary>
/// updates the fields in the file with a given value
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public override void UpdateValue(TMTGlobalKeys key, string value)
{
var pattern = TMTKey.GetKey(key);
for (int i = 0; i < _allLines.Count; i++)
{
if (_allLines[i].Contains(pattern))
{
_allLines[i] = _allLines[i].Replace(pattern, value);
}
}
}
/// <summary>
/// updates the files in the file with the given value
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="channelNumber"></param>
public override void UpdateValue(TMTChannelKeys key, string value, int channelNumber)
{
var pattern = TMTKey.GetKey(key, channelNumber);
for (int i = 0; i < _allLines.Count; i++)
{
if (_allLines[i].Contains(pattern))
{
_allLines[i] = _allLines[i].Replace(pattern, value);
}
}
}
/// <summary>
/// all lines in the TMT file
/// </summary>
private readonly List<string> _allLines = new List<string>();
/// <summary>
/// returns all lines in the TMT file
/// </summary>
/// <returns></returns>
public override string[] GetAllLines()
{
return _allLines.ToArray();
}
}
}

View File

@@ -0,0 +1,102 @@
using System.Collections.Generic;
using System.Linq;
namespace DTS.Common.Classes.TMAT
{
/// <summary>
/// this class handles a TMATS template split into two files
/// </summary>
public class TmtSplitFile : TmtBase
{
private readonly List<string> _lines = new List<string>();
private readonly Dictionary<int, List<string>> _allChannels = new Dictionary<int, List<string>>();
private readonly List<string> _channelTemplate = new List<string>();
public override string[] GetAllLines()
{
if (!_allChannels.Any()) { return _lines.ToArray(); }
var lines = new List<string>(_lines.ToArray());
var min = _allChannels.Keys.Min();
var max = _allChannels.Keys.Max();
for( var i = min; i<= max; i++)
{
if (_allChannels.ContainsKey(i))
{
lines.AddRange(_allChannels[i].ToArray());
}
}
return lines.ToArray();
}
private void AddChannelIfNeeded(int channelNumber)
{
if (!_allChannels.ContainsKey(channelNumber))
{
_allChannels.Add(channelNumber, _channelTemplate.ToList());
}
}
/// <summary>
/// updates the files in the file with a given value
/// </summary>
public override void UpdateValue(TMTChannelKeysEx key, string value, int channelNumber)
{
AddChannelIfNeeded(channelNumber);
var lines = _allChannels[channelNumber];
var pattern = TMTKey.GetKey(key);
for (int i = 0; i < lines.Count; i++)
{
if (lines[i].Contains(pattern))
{
lines[i] = lines[i].Replace(pattern, value);
}
}
}
/// <summary>
/// updates the fields in the file with a given value
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public override void UpdateValue(TMTGlobalKeys key, string value)
{
var pattern = TMTKey.GetKey(key);
for (int i = 0; i < _lines.Count; i++)
{
if (_lines[i].Contains(pattern))
{
_lines[i] = _lines[i].Replace(pattern, value);
}
}
}
/// <summary>
/// updates the files in the file with the given value
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="channelNumber"></param>
public override void UpdateValue(TMTChannelKeys key, string value, int channelNumber)
{
var pattern = TMTKey.GetKey(key, channelNumber);
for (int i = 0; i < _lines.Count; i++)
{
if (_lines[i].Contains(pattern))
{
_lines[i] = _lines[i].Replace(pattern, value);
}
}
}
public TmtSplitFile(string dasTemplate, string channelTemplate)
{
if (System.IO.File.Exists(dasTemplate))
{
_lines.AddRange(System.IO.File.ReadAllLines(dasTemplate));
}
if (System.IO.File.Exists(channelTemplate))
{
_channelTemplate.AddRange(System.IO.File.ReadAllLines(channelTemplate));
}
}
}
}

View File

@@ -0,0 +1,248 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using DTS.Common.Utilities.Logging;
namespace DTS.Common.Classes
{
public abstract class TagAwareBase : Base.BasePropertyChanged
{
public enum TagTypes
{
User,
Group,
Template,
TestSetup,
Sensors,
SensorModels
}
public abstract TagTypes TagType { get; }
#region Tags
public byte[] TagsBlobBytes
{
get
{
var result = new byte[TagIDs.Length * sizeof(int)];
Buffer.BlockCopy(TagIDs, 0, result, 0, result.Length);
return result;
}
set
{
if (value.Length < sizeof(int)) return;
var tagsBlob = new int[value.Length / sizeof(int)];
try
{
Buffer.BlockCopy(value, 0, tagsBlob, 0, value.Length);
TagIDs = tagsBlob;
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
}
private int[] _tagIDs = new int[0];
public int[] TagIDs
{
get => _tagIDs;
set => _tagIDs = value ?? new int[0];
}
public void SetTagsFromCommaSeparatedString(string tagText, Tags.GetSqlCommandDelegate getSqlCommand)
{
//if (string.IsNullOrEmpty(tagText)) { return; } // http://fogbugz/fogbugz/default.asp?7176
SetTags(tagText.Split(','), getSqlCommand);
}
public virtual void SetTags(string[] tagsText, Tags.GetSqlCommandDelegate getSqlCommand)
{
Tags.AddRange(tagsText, getSqlCommand);
TagIDs = Tags.GetIDsFromTagText(tagsText, getSqlCommand);
OnPropertyChanged("TagIDs");
}
public string GetTagsAsCommaSeparatedString(Tags.GetSqlCommandDelegate getSqlCommand)
{
var sb = new StringBuilder();
var tagArray = GetTagsArray(getSqlCommand);
foreach (var s in tagArray)
{
if (sb.Length > 0) { sb.Append(","); }
sb.Append(s);
}
return sb.ToString();
}
#region ITagAware
public virtual string[] GetTagsArray(Tags.GetSqlCommandDelegate getSqlCommand)
{
return Tags.GetTagTextFromIDs(TagIDs, getSqlCommand);
}
public virtual int[] GetTagIDs() { return TagIDs; }
public virtual void RemoveTags(string[] tagsText)
{
// remove tags!!!
//-;
}
public bool TagCompatible(string tags, Tags.GetSqlCommandDelegate getSqlCommand)
{
//Make sure there are Tags to check
if (string.IsNullOrWhiteSpace(tags)) return true;
var newTagsArray = tags.Split(',');
//Make sure all Tags are not empty strings
if (newTagsArray.All(string.IsNullOrWhiteSpace)) return true;
var comparisonArray = GetTagsArray(getSqlCommand);
foreach (var tag in newTagsArray)
{
//If a Tag is an empty string, ignore it
if (string.IsNullOrWhiteSpace(tag)) continue;
if (comparisonArray.Contains(tag.Trim()))
{
return true;
}
}
return false;
}
public virtual bool TagCompatible(int[] tags)
{
return !tags.Any() || HasIntersectingTag(tags);
}
public virtual bool HasIntersectingTag(int[] tags)
{
return tags.Intersect(TagIDs).Any();
}
#endregion
#endregion
public void InsertTagsFromCommaSeparatedString(int id, TagTypes tagType, string tags, Tags.GetSqlCommandDelegate getSqlCommand)
{
SetTagsFromCommaSeparatedString(tags, getSqlCommand);
Commit(id, tagType, getSqlCommand);
}
public void Commit(int id, TagTypes tagType, Tags.GetSqlCommandDelegate getSqlCommand)
{
using (var cmd = getSqlCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = @"sp_TagAssignmentsDelete";
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectID", SqlDbType.Int) { Value = id });
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.SmallInt) { Value = tagType });
var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
if (!TagIDs.Any()) return;
foreach (var tagId in TagIDs)
{
using (var cmd = getSqlCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = @"sp_TagAssignmentsInsert";
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectID", SqlDbType.Int) { Value = id });
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.SmallInt) { Value = tagType });
cmd.Parameters.Add(new SqlParameter("@TagID", SqlDbType.Int) { Value = tagId });
var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
public List<int> GetTagIdList(int objectId, TagTypes tagType, Tags.GetSqlCommandDelegate getSqlCommand)
{
var tagIdList = new List<int>();
try
{
using (var cmd = getSqlCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = @"sp_TagAssignmentsGet";
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.Int) { Value = tagType });
#endregion params
//cmd.ExecuteNonQuery();
var reader = cmd.ExecuteReader();
while (reader.Read())
{
if (Convert.ToInt32(reader["ObjectID"]) != objectId) continue;
var tagId = Convert.ToInt32(reader["TagID"]);
if (!tagIdList.Contains(tagId))
{
tagIdList.Add(tagId);
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log("failed to retrieve object tags", ex);
}
return tagIdList;
}
}
}

View File

@@ -0,0 +1,373 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DTS.Common.Utilities.Logging;
// ReSharper disable InconsistentNaming
// ReSharper disable once CheckNamespace
namespace DTS.Common.Classes
{
public class Tags
{
/// <summary>
/// represents a single tag, which is composed of an ID and a string of text
/// we don't currently let you obsolete, delete, or edit tags, just add
/// </summary>
public class Tag: ICloneable
{
public Tag(string tagText, int tagId)
{
ID = tagId;
Text = tagText;
IsObsolete = false;
}
public const int INVALID_ID = -1;
public int ID { get; set; }
public string Text { get; set; }
public bool IsObsolete { get; set; }
public Tag(Tag copy)
{
ID = copy.ID;
Text = copy.Text;
IsObsolete = copy.IsObsolete;
}
public Tag(IDataRecord reader)
{
try
{
ID = Convert.ToInt32(reader["TagId"]);
IsObsolete = Convert.ToBoolean(reader["Obsolete"]);
Text = Convert.ToString(reader["TagText"]);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
public Tag(DataRow dr)
{
try
{
IsObsolete = Convert.ToBoolean(dr["Obsolete"]);
ID = Convert.ToInt32(dr["TagId"]);
Text = Convert.ToString(dr["TagFields"]);
}
catch (Exception ex) { APILogger.Log(ex); }
}
public object Clone()
{
return new Tag(this);
}
}
private static Tags _tagsInstance;
//public static Tags TagsInstance
//{
// get
// {
// if (null == _tagsInstance) { _tagsInstance = new Tags(); }
// return _tagsInstance;
// }
//}
public static Tags GetTagsInstance(GetSqlCommandDelegate getSqlCommand)
{
if( null == _tagsInstance)
{
_tagsInstance = new Tags(getSqlCommand);
}
return _tagsInstance;
}
private static readonly object LOCK_OBJECT = new object();
public Tags(GetSqlCommandDelegate getSqlCommand)
{
_tagsLookup = new Dictionary<string, Tag>();
UpdateList(getSqlCommand);
}
/// <summary>
/// holds a cached collection of tags. This collection however is currently only populated on startup
/// and not updated except explicitly when a user adds a tag
/// </summary>
// ReSharper disable once RedundantDefaultMemberInitializer
private readonly Dictionary<string, Tag> _tagsLookup = null;
/// <summary>
/// Adds a tag if not present in memory cache to db
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool AddTag(string tagText, GetSqlCommandDelegate getSqlCommand)
{
if (string.IsNullOrEmpty(tagText)) { return false; }
// is it already in the dictionary?
var tags = Tags.GetTagsInstance(getSqlCommand);
if (tags.ContainsTag(tagText)) return false;
tags.Commit(new Tag(tagText, Tag.INVALID_ID), getSqlCommand);
return true;
}
/// <summary>
/// Changes the ID of a tag during database migration
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool MigrateTag(string tagText, GetSqlCommandDelegate getSqlCommand)
{
if (string.IsNullOrEmpty(tagText)) { return false; }
Tags.GetTagsInstance(getSqlCommand).Commit(new Tag(tagText, Tag.INVALID_ID), getSqlCommand);
return true;
}
/// <summary>
/// commits a tag to db if doesn't already exist in db
/// </summary>
/// <param name="tag"></param>
private void Commit(Tag tag, GetSqlCommandDelegate getSqlCommand)
{
try
{
if (-1 == GetIDFromTagText(tag.Text, getSqlCommand))
{
Insert(tag, getSqlCommand);
}
else { UpdateAll(tag, getSqlCommand); }
lock (LOCK_OBJECT)
{
_tagsLookup[tag.Text] = tag;
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
private void UpdateAll(Tag tag, GetSqlCommandDelegate getSqlCommand)
{
//nothing to do currently? (we don't let you rename or edit, or obsolete, or delete ...)
tag.ID = GetTagIdFromText(tag.Text, getSqlCommand);
}
public delegate SqlCommand GetSqlCommandDelegate(bool bNewConnection);
/// <summary>
/// inserts a tag into the db
/// </summary>
/// <param name="tag"></param>
private void Insert(Tag tag, GetSqlCommandDelegate getSqlCommand)
{
using (var cmd = getSqlCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_TagsInsert";
#region params
cmd.Parameters.Add(new SqlParameter("@TagText", SqlDbType.NVarChar, 255) {Value = tag.Text});
cmd.Parameters.Add(new SqlParameter("@Obsolete", SqlDbType.Bit) {Value = tag.IsObsolete});
var newIdParam = new SqlParameter("@new_id", SqlDbType.Int) {Direction = ParameterDirection.Output};
cmd.Parameters.Add(newIdParam);
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) {Direction = ParameterDirection.Output};
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
tag.ID = int.Parse(newIdParam.Value.ToString());
}
finally
{
cmd.Connection.Dispose();
}
}
}
/// <summary>
/// retrieves a string text associated with an ID FROM CACHED copies
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private string GetTagTextFromId(int id)
{
lock (LOCK_OBJECT)
{
if (_tagsLookup == null) return null;
var e = _tagsLookup.GetEnumerator();
while (e.MoveNext())
{
if (e.Current.Value.ID != id) continue;
var returnText = e.Current.Value.Text;
e.Dispose();
return returnText;
}
}
return null;
}
/// <summary>
/// Gets an ID for a given tag text FROM DB
/// returns InvalidID if not found
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
private int GetTagIdFromText(string text, GetSqlCommandDelegate getSqlCommand)
{
using (var cmd = getSqlCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_TagsGetId";
#region params
cmd.Parameters.Add(new SqlParameter("@TagText", SqlDbType.NVarChar, 255) {Value = text});
var tagIdParam = new SqlParameter("@TagId", SqlDbType.Int) {Direction = ParameterDirection.Output};
cmd.Parameters.Add(tagIdParam);
#endregion params
cmd.ExecuteNonQuery();
if (DBNull.Value.Equals(tagIdParam.Value))
{
return Tag.INVALID_ID;
}
var tagIdtemp = int.Parse(tagIdParam.Value.ToString());
return tagIdtemp == 0 ? Tag.INVALID_ID : tagIdtemp;
}
finally
{
cmd.Connection.Dispose();
}
}
}
/// <summary>
/// returns true if a given tag text is contained in cached in memory tags
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public bool ContainsTag(string text)
{
lock (LOCK_OBJECT)
{
return _tagsLookup.ContainsKey(text);
}
}
/// <summary>
/// adds multiple tags at once
/// note that tags will have their start trimmed before commiting
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool[] AddRange(string[] tagText, GetSqlCommandDelegate getSqlCommand)
{
List<bool> rv = new List<bool>();
if (null == tagText || 0 == tagText.Length) { return null; }
foreach (string s in tagText)
{
var tag = s.TrimStart();
rv.Add(AddTag(tag, getSqlCommand));
}
return rv.ToArray();
}
/// <summary>
/// gets an ID for a given tag text FROM DB
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static int GetIDFromTagText(string tagText, GetSqlCommandDelegate getSqlCommand)
{
return GetTagsInstance(getSqlCommand).GetTagIdFromText(tagText, getSqlCommand);
}
/// <summary>
/// gets an array of ids given an array of tag texts
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static int[] GetIDsFromTagText(string[] tagText, GetSqlCommandDelegate getSqlCommand)
{
if (null == tagText || 0 == tagText.Length) { return null; }
return tagText.Select(s => s.TrimStart()).Select(text => GetIDFromTagText(text, getSqlCommand)).Where(id => id != Tag.INVALID_ID).ToArray();
}
/// <summary>
/// returns a string for a given id from memory cache
/// returns null if it doesn't exist or is an invalid id
/// </summary>
/// <param name="tagID"></param>
/// <returns></returns>
public static string GetTagTextFromID(int tagID, GetSqlCommandDelegate getSqlCommand)
{
if (0 > tagID || tagID == Tag.INVALID_ID)
{
// Not a valid ID
return null;
}
return GetTagsInstance(getSqlCommand).GetTagTextFromId(tagID);
}
/// <summary>
/// returns an array of tag text given an array of tag ids.
/// skips invalid tags or tag text
/// </summary>
/// <param name="tagId"></param>
/// <returns></returns>
public static string[] GetTagTextFromIDs(int[] tagId, GetSqlCommandDelegate getSqlCommand)
{
if (null == tagId || 0 == tagId.Length) { return new string [0]; }
return tagId.Where(i => i != Tag.INVALID_ID).Select(i => GetTagTextFromID(i,getSqlCommand)).Where(tag => !string.IsNullOrWhiteSpace(tag)).ToArray();
}
/// <summary>
/// retrieves all tags and updates the cached dictionary of tags
/// </summary>
public void UpdateList(GetSqlCommandDelegate getSqlCommand)
{
lock (LOCK_OBJECT)
{
_tagsLookup.Clear();
using (var cmd = getSqlCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_TagsGet";
cmd.Parameters.Add(new SqlParameter("@TagId", SqlDbType.Int) {Value = null});
var reader = cmd.ExecuteReader();
while (reader.Read())
{
var t = new Tag(reader);
if (t.ID == 0) continue;
_tagsLookup[t.Text] = t;
}
reader.Close();
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
}
}

View File

@@ -0,0 +1,63 @@
using DTS.Common.Interface.Tags;
using System.Data;
namespace DTS.Common.Classes.Tags
{
/// <summary>
/// describes a database record for a tag
/// <inheritdoc cref="ITag"/>
/// </summary>
/// <summary>
/// represents a single tag, which is composed of an ID and a string of text
/// we don't currently let you obsolete, delete, or edit tags, just add
/// </summary>
public class Tag : Base.BasePropertyChanged, ITag
{
public Tag(string tagText, int tagId)
{
ID = tagId;
Text = tagText;
IsObsolete = false;
}
public const int INVALID_ID = -1;
private int _id;
public int ID
{
get => _id;
set => SetProperty(ref _id, value, "ID");
}
private string _text = "";
public string Text
{
get => _text;
set => SetProperty(ref _text, value, "Text");
}
private bool _isObsolete = false;
public bool IsObsolete
{
get => _isObsolete;
set => SetProperty(ref _isObsolete, value, "IsObsolete");
}
public Tag(Tag copy)
{
ID = copy.ID;
Text = copy.Text;
IsObsolete = copy.IsObsolete;
}
public Tag(IDataReader reader)
{
ID = Utility.GetInt(reader, "TagId");
IsObsolete = Utility.GetBool(reader, "Obsolete");
Text = Utility.GetString(reader, "TagText");
}
public Tag() { }
public object Clone()
{
return new Tag(this);
}
}
}

View File

@@ -0,0 +1,37 @@
using DTS.Common.Base;
using DTS.Common.Interface.Tags;
using System.Data;
namespace DTS.Common.Classes.Tags
{
public class TagAssignment : BasePropertyChanged, ITagAssignment
{
private int _objectId;
public int ObjectID
{
get => _objectId;
set => SetProperty(ref _objectId, value, "ObjectID");
}
private int _tagId;
public int TagID
{
get => _tagId;
set => SetProperty(ref _tagId, value, "TagID");
}
private TagTypes _tagType;
public TagTypes ObjectType
{
get => _tagType;
set => SetProperty(ref _tagType, value, "TagType");
}
public TagAssignment() { }
public TagAssignment(IDataReader reader)
{
TagID = Utility.GetInt(reader, "TagID");
ObjectID = Utility.GetInt(reader, "ObjectID");
ObjectType = (TagTypes)Utility.GetShort(reader, "ObjectType");
}
}
}

View File

@@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTS.Common.Classes.Tags;
using DTS.Common.Interface.Tags;
using DTS.Common.Utilities.Logging;
namespace DTS.Common.Classes
{
public abstract class TagAwareBase : Base.BasePropertyChanged
{
public abstract TagTypes TagType { get; }
#region Tags
public byte[] TagsBlobBytes
{
get
{
var result = new byte[TagIDs.Length * sizeof(int)];
Buffer.BlockCopy(TagIDs, 0, result, 0, result.Length);
return result;
}
set
{
if (value.Length < sizeof(int)) return;
var tagsBlob = new int[value.Length / sizeof(int)];
try
{
Buffer.BlockCopy(value, 0, tagsBlob, 0, value.Length);
TagIDs = tagsBlob;
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
}
private int[] _tagIDs = new int[0];
public int[] TagIDs
{
get => _tagIDs;
set => _tagIDs = value ?? new int[0];
}
public void SetTagsFromCommaSeparatedString(string tagText,
Tags.TagsInstance.GetSqlCommandDelegate getSqlCommand,
Tags.TagsInstance.TagsGetDelegate tagsGet,
Tags.TagsInstance.TagsGetIdDelegate tagsGetId,
Tags.TagsInstance.TagsInsertDelegate tagsInsert)
{
//if (string.IsNullOrEmpty(tagText)) { return; } // http://fogbugz/fogbugz/default.asp?7176
SetTags(tagText.Split(','), getSqlCommand, tagsGet, tagsGetId, tagsInsert);
}
public virtual void SetTags(string[] tagsText, Tags.TagsInstance.GetSqlCommandDelegate getSqlCommand,
Tags.TagsInstance.TagsGetDelegate tagsGet, Tags.TagsInstance.TagsGetIdDelegate tagsGetId,
Tags.TagsInstance.TagsInsertDelegate tagsInsert)
{
Tags.TagsInstance.AddRange(tagsText, getSqlCommand, tagsGet, tagsGetId, tagsInsert);
TagIDs = Tags.TagsInstance.GetIDsFromTagText(tagsText, tagsGet, tagsGetId);
OnPropertyChanged("TagIDs");
}
public string GetTagsAsCommaSeparatedString(Tags.TagsInstance.TagsGetDelegate tagsGet)
{
var sb = new StringBuilder();
var tagArray = GetTagsArray(tagsGet);
foreach (var s in tagArray)
{
if (sb.Length > 0) { sb.Append(","); }
sb.Append(s);
}
return sb.ToString();
}
#region ITagAware
public virtual string[] GetTagsArray(Tags.TagsInstance.TagsGetDelegate tagsGet)
{
return Tags.TagsInstance.GetTagTextFromIDs(TagIDs, tagsGet);
}
public virtual int[] GetTagIDs() { return TagIDs; }
public virtual void RemoveTags(string[] tagsText)
{
// remove tags!!!
//-;
}
public bool TagCompatible(string tags, Tags.TagsInstance.TagsGetDelegate tagsGet)
{
//Make sure there are Tags to check
if (string.IsNullOrWhiteSpace(tags)) return true;
var newTagsArray = tags.Split(',');
//Make sure all Tags are not empty strings
if (Array.TrueForAll(newTagsArray, string.IsNullOrWhiteSpace)) return true;
var comparisonArray = GetTagsArray(tagsGet);
foreach (var tag in newTagsArray)
{
//If a Tag is an empty string, ignore it
if (string.IsNullOrWhiteSpace(tag)) continue;
if (comparisonArray.Contains(tag.Trim()))
{
return true;
}
}
return false;
}
public virtual bool TagCompatible(int[] tags)
{
return !tags.Any() || HasIntersectingTag(tags);
}
public virtual bool HasIntersectingTag(int[] tags)
{
return tags.Intersect(TagIDs).Any();
}
#endregion
#endregion
public void InsertTagsFromCommaSeparatedString(int id, TagTypes tagType, string tags,
Tags.TagsInstance.GetSqlCommandDelegate getSqlCommand, Tags.TagsInstance.TagsGetDelegate tagsGet,
Tags.TagsInstance.TagsGetIdDelegate tagsIdGet, Tags.TagsInstance.TagsInsertDelegate tagsInsert,
Tags.TagsInstance.TagAssignmentsDelete tagAssignmentsDelete, Tags.TagsInstance.TagAssignmentsInsert tagAssignmentsInsert)
{
SetTagsFromCommaSeparatedString(tags, getSqlCommand, tagsGet, tagsIdGet, tagsInsert);
Commit(id, tagType, tagAssignmentsDelete, tagAssignmentsInsert);
}
public void Commit(int id, TagTypes tagType,
Tags.TagsInstance.TagAssignmentsDelete tagAssignmentsDelete,
Tags.TagsInstance.TagAssignmentsInsert tagAssignmentInsert)
{
_ = tagAssignmentsDelete(tagType, id);
if (!TagIDs.Any()) return;
foreach (var tagId in TagIDs)
{
_ = tagAssignmentInsert(new TagAssignment() { ObjectID = id, ObjectType = tagType, TagID = tagId });
}
}
public List<int> GetTagIdList(int objectId, TagTypes tagType,
Tags.TagsInstance.TagAssignmentsGet tagAssignmentsGet)
{
var tagIdList = new List<int>();
var hr = tagAssignmentsGet(tagType, out var records);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
if (record.ObjectID != objectId) { continue; }
if (!tagIdList.Contains(record.TagID))
{
tagIdList.Add(record.TagID);
}
}
}
return tagIdList;
}
}
}

View File

@@ -0,0 +1,250 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DTS.Common.Interface.Tags;
using DTS.Common.Utilities.Logging;
// ReSharper disable InconsistentNaming
// ReSharper disable once CheckNamespace
namespace DTS.Common.Classes.Tags
{
public class TagsInstance
{
private static TagsInstance _tagsInstance;
public static TagsInstance GetTagsInstance(TagsGetDelegate tagsGet)
{
if (null == _tagsInstance)
{
_tagsInstance = new TagsInstance(tagsGet);
}
return _tagsInstance;
}
private static readonly object LOCK_OBJECT = new object();
public TagsInstance(TagsGetDelegate tagsGet)
{
_tagsLookup = new Dictionary<string, ITag>();
UpdateList(tagsGet);
}
/// <summary>
/// holds a cached collection of tags. This collection however is currently only populated on startup
/// and not updated except explicitly when a user adds a tag
/// </summary>
// ReSharper disable once RedundantDefaultMemberInitializer
private readonly Dictionary<string, ITag> _tagsLookup = null;
/// <summary>
/// Adds a tag if not present in memory cache to db
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool AddTag(string tagText, GetSqlCommandDelegate getSqlCommand, TagsGetDelegate tagsGet,
TagsGetIdDelegate tagsGetId, TagsInsertDelegate tagsInsert)
{
if (string.IsNullOrEmpty(tagText)) { return false; }
// is it already in the dictionary?
var tags = GetTagsInstance(tagsGet);
if (tags.ContainsTag(tagText)) return false;
tags.Commit(new Tag(tagText, Tag.INVALID_ID), tagsGet, tagsGetId, tagsInsert);
return true;
}
/// <summary>
/// Changes the ID of a tag during database migration
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool MigrateTag(string tagText, GetSqlCommandDelegate getSqlCommand, TagsGetDelegate tagsGet,
TagsGetIdDelegate tagsGetId, TagsInsertDelegate tagsInsert)
{
if (string.IsNullOrEmpty(tagText)) { return false; }
GetTagsInstance(tagsGet).Commit(new Tag(tagText, Tag.INVALID_ID), tagsGet, tagsGetId, tagsInsert);
return true;
}
/// <summary>
/// commits a tag to db if doesn't already exist in db
/// </summary>
/// <param name="tag"></param>
private void Commit(Tag tag, TagsGetDelegate tagsGet,
TagsGetIdDelegate tagsGetId, TagsInsertDelegate tagsInsert)
{
try
{
if (-1 == GetIDFromTagText(tag.Text, tagsGet, tagsGetId))
{
Insert(tag, tagsInsert);
}
else { UpdateAll(tag, tagsGetId); }
lock (LOCK_OBJECT)
{
_tagsLookup[tag.Text] = tag;
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
private void UpdateAll(Tag tag, TagsGetIdDelegate tagsGetId)
{
//nothing to do currently? (we don't let you rename or edit, or obsolete, or delete ...)
tag.ID = GetTagIdFromText(tag.Text, tagsGetId);
}
public delegate ulong TagAssignmentsGet(TagTypes? tagType, out ITagAssignment[] records);
public delegate SqlCommand GetSqlCommandDelegate(bool bNewConnection);
public delegate ulong TagAssignmentsDelete(TagTypes objectType, int objectId);
public delegate ulong TagAssignmentsInsert(ITagAssignment tagAssignment);
public delegate ulong TagsGetIdDelegate(string text, out int? id);
public delegate ulong TagsGetDelegate(int? id, out ITag[] tags);
public delegate ulong TagsInsertDelegate(ref ITag tag);
/// <summary>
/// inserts a tag into the db
/// </summary>
/// <param name="tag"></param>
private void Insert(Tag tag, TagsInsertDelegate tagsInsert)
{
var itag = (ITag)tag;
_ = tagsInsert(ref itag);
}
/// <summary>
/// retrieves a string text associated with an ID FROM CACHED copies
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private string GetTagTextFromId(int id)
{
lock (LOCK_OBJECT)
{
if (_tagsLookup == null) return null;
var e = _tagsLookup.GetEnumerator();
while (e.MoveNext())
{
if (e.Current.Value.ID != id) continue;
var returnText = e.Current.Value.Text;
e.Dispose();
return returnText;
}
}
return null;
}
/// <summary>
/// Gets an ID for a given tag text FROM DB
/// returns InvalidID if not found
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
private int GetTagIdFromText(string text, TagsGetIdDelegate tagsGetId)
{
var hr = tagsGetId(text, out var id);
if (0 != hr || null == id)
{
return Tag.INVALID_ID;
}
return (int)id;
}
/// <summary>
/// returns true if a given tag text is contained in cached in memory tags
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public bool ContainsTag(string text)
{
lock (LOCK_OBJECT)
{
return _tagsLookup.ContainsKey(text);
}
}
/// <summary>
/// adds multiple tags at once
/// note that tags will have their start trimmed before commiting
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool[] AddRange(string[] tagText, GetSqlCommandDelegate getSqlCommand,
TagsGetDelegate tagsGet, TagsGetIdDelegate tagsGetId, TagsInsertDelegate tagsInsert)
{
List<bool> rv = new List<bool>();
if (null == tagText || 0 == tagText.Length) { return null; }
foreach (string s in tagText)
{
var tag = s.TrimStart();
rv.Add(AddTag(tag, getSqlCommand, tagsGet, tagsGetId, tagsInsert));
}
return rv.ToArray();
}
/// <summary>
/// gets an ID for a given tag text FROM DB
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static int GetIDFromTagText(string tagText, TagsGetDelegate tagsGet,
TagsGetIdDelegate tagsGetId)
{
return GetTagsInstance(tagsGet).GetTagIdFromText(tagText, tagsGetId);
}
/// <summary>
/// gets an array of ids given an array of tag texts
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static int[] GetIDsFromTagText(string[] tagText, TagsGetDelegate tagsGet,
TagsGetIdDelegate tagsGetId)
{
if (null == tagText || 0 == tagText.Length) { return null; }
return tagText.Select(s => s.TrimStart()).Select(text => GetIDFromTagText(text, tagsGet, tagsGetId))
.Where(id => id != Tag.INVALID_ID).ToArray();
}
/// <summary>
/// returns a string for a given id from memory cache
/// returns null if it doesn't exist or is an invalid id
/// </summary>
/// <param name="tagID"></param>
/// <returns></returns>
public static string GetTagTextFromID(int tagID, TagsGetDelegate tagsGet)
{
if (0 > tagID || tagID == Tag.INVALID_ID)
{
// Not a valid ID
return null;
}
return GetTagsInstance(tagsGet).GetTagTextFromId(tagID);
}
/// <summary>
/// returns an array of tag text given an array of tag ids.
/// skips invalid tags or tag text
/// </summary>
/// <param name="tagId"></param>
/// <returns></returns>
public static string[] GetTagTextFromIDs(int[] tagId, TagsGetDelegate tagsGet)
{
if (null == tagId || 0 == tagId.Length) { return new string[0]; }
return tagId.Where(i => i != Tag.INVALID_ID).Select(i => GetTagTextFromID(i, tagsGet)).Where(tag => !string.IsNullOrWhiteSpace(tag)).ToArray();
}
/// <summary>
/// retrieves all tags and updates the cached dictionary of tags
/// </summary>
public void UpdateList(TagsGetDelegate tagsGet)
{
var hr = tagsGet(null, out var tags);
if (0 == hr && null != tags && tags.Any())
{
lock (LOCK_OBJECT)
{
_tagsLookup.Clear();
foreach (var tag in tags)
{
_tagsLookup[tag.Text] = tag;
}
}
}
}
}
}

View File

@@ -0,0 +1,130 @@
using DTS.Common.Base.Classes;
using DTS.Common.Interface.TestMetaData;
using DTS.Common.Utilities.Logging;
using System;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace DTS.Common.Classes.CustomerDetails
{
public class CustomerDetailsDbRecord : Base.BasePropertyChanged, ICustomerDetailsDbRecord
{
private int _customerId = -1;
[ReadOnly(true)]
[Browsable(false)]
public int CustomerId
{
get => _customerId;
set => SetProperty(ref _customerId, value, "CustomerId");
}
private string _name = "";
[ReadOnly(true)]
[Browsable(false)]
public string Name
{
get => _name;
set => SetProperty(ref _name, value, "Name");
}
private string _customerName = "";
[DisplayResource("CustomerName")]
public string CustomerName
{
get => _customerName;
set => SetProperty(ref _customerName, value, "CustomerName");
}
private string _customerTestRefNumber = "";
[DisplayResource("CustomerTestRefNumber")]
public string CustomerTestRefNumber
{
get => _customerTestRefNumber;
set => SetProperty(ref _customerTestRefNumber, value, "CustomerTestRefNumber");
}
private string _projectRefNumber = "NOVALUE";
[DisplayResource("ProjectRefNumber")]
public string ProjectRefNumber
{
get => _projectRefNumber;
set => SetProperty(ref _projectRefNumber, value, "ProjectRefNumber");
}
private string _customerOrderNumber = "NOVALUE";
[DisplayResource("CustomerOrderNumber")]
public string CustomerOrderNumber
{
get => _customerOrderNumber;
set => SetProperty(ref _customerOrderNumber, value, "CustomerOrderNumber");
}
private string _customerCostUnit = "NOVALUE";
[DisplayResource("CustomerCostUnit")]
public string CustomerCostUnit
{
get => _customerCostUnit;
set => SetProperty(ref _customerCostUnit, value, "CustomerCostUnit");
}
private bool _localOnly = false;
[Browsable(false)]
[ReadOnly(true)]
public bool LocalOnly
{
get => _localOnly;
set => SetProperty(ref _localOnly, value, "LocalOnly");
}
private DateTime _lastModified = DateTime.MinValue;
[Browsable(false)]
[ReadOnly(true)]
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private string _lastModifiedBy = "";
[Browsable(false)]
[ReadOnly(true)]
public string LastModifiedBy
{
get => _lastModifiedBy;
set => SetProperty(ref _lastModifiedBy, value, "LastModifiedBy");
}
private int _version = -1;
[Browsable(false)]
[ReadOnly(true)]
public int Version
{
get => _version;
set => SetProperty(ref _version, value, "Version");
}
public CustomerDetailsDbRecord(ICustomerDetailsDbRecord customerDetailsDbRecord)
{
Name = customerDetailsDbRecord.Name;
CustomerName = customerDetailsDbRecord.CustomerName;
CustomerTestRefNumber = customerDetailsDbRecord.CustomerTestRefNumber;
ProjectRefNumber = customerDetailsDbRecord.ProjectRefNumber;
CustomerOrderNumber = customerDetailsDbRecord.CustomerOrderNumber;
CustomerCostUnit = customerDetailsDbRecord.CustomerCostUnit;
LocalOnly = customerDetailsDbRecord.LocalOnly;
LastModified = customerDetailsDbRecord.LastModified;
LastModifiedBy = customerDetailsDbRecord.LastModifiedBy;
Version = customerDetailsDbRecord.Version;
}
public CustomerDetailsDbRecord() { }
public CustomerDetailsDbRecord(IDataReader reader)
{
Name = Utility.GetString(reader, "Name");
CustomerName = Utility.GetString(reader, "CustomerName");
CustomerTestRefNumber = Utility.GetString(reader, "CustomerTestRefNumber");
ProjectRefNumber = Utility.GetString(reader, "ProjectRefNumber");
CustomerOrderNumber = Utility.GetString(reader, "CustomerOrderNumber");
CustomerCostUnit = Utility.GetString(reader, "CustomerCostUnit");
LocalOnly = Utility.GetBool(reader, "LocalOnly");
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastModifiedBy = Utility.GetString(reader, "LastModifiedBy");
Version = Utility.GetInt(reader, "Version");
}
public bool IsInvalidBlank()
{
return string.IsNullOrWhiteSpace(Name);
}
}
}

View File

@@ -0,0 +1,161 @@
using DTS.Common.Base.Classes;
using DTS.Common.Interface.TestMetaData;
using DTS.Common.Utilities.Logging;
using System;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace DTS.Common.Classes.LabratoryDetails
{
public class LabratoryDetailsDbRecord : Base.BasePropertyChanged, ILabratoryDetailsDbRecord
{
private int _labratoryId = -1;
[Browsable(false)]
[ReadOnly(true)]
public int LabratoryId
{
get => _labratoryId;
set => SetProperty(ref _labratoryId, value, "LabratoryId");
}
private string _name = "";
[Browsable(false)]
[ReadOnly(true)]
public string Name
{
get => _name;
set => SetProperty(ref _name, value, "Name");
}
private string _labratoryName = string.Empty;
[DisplayResource("LabratoryName")]
public string LabratoryName
{
get => _labratoryName;
set => SetProperty(ref _labratoryName, value, "LabratoryName");
}
private string _labratoryContactName = string.Empty;
[DisplayResource("LabratoryContactName")]
public string LabratoryContactName
{
get => _labratoryContactName;
set => SetProperty(ref _labratoryContactName, value, "LabratoryContactName");
}
private string _labratoryContactPhone = "NOVALUE";
[DisplayResource("LabratoryContactPhone")]
public string LabratoryContactPhone
{
get => _labratoryContactPhone;
set => SetProperty(ref _labratoryContactPhone, value, "LabratoryContactPhone");
}
private string _labratoryContactFax = "NOVALUE";
[DisplayResource("LabratoryContactFax")]
public string LabratoryContactFax
{
get => _labratoryContactFax;
set => SetProperty(ref _labratoryContactFax, value, "LabratoryContactFax");
}
private string _labratoryContactEmail = "NOVALUE";
[DisplayResource("LabratoryContactEmail")]
public string LabratoryContactEmail
{
get => _labratoryContactEmail;
set => SetProperty(ref _labratoryContactEmail, value, "LabratoryContactEmail");
}
private string _labratoryTestRefNumber = string.Empty;
[DisplayResource("LabratoryTestRefNumber")]
public string LabratoryTestRefNumber
{
get => _labratoryTestRefNumber;
set => SetProperty(ref _labratoryTestRefNumber, value, "LabratoryTestRefNumber");
}
private string _labratoryProjectRefNumber = string.Empty;
[DisplayResource("LabratoryProjectRefNumber")]
public string LabratoryProjectRefNumber
{
get => _labratoryProjectRefNumber;
set => SetProperty(ref _labratoryProjectRefNumber, value, "LabratoryProjectRefNumber");
}
private DateTime _lastModified = DateTime.MinValue;
[Browsable(false)]
[ReadOnly(true)]
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, "LastModified");
}
private string _lastModifiedBy = "";
[Browsable(false)]
[ReadOnly(true)]
public string LastModifiedBy
{
get => _lastModifiedBy;
set => SetProperty(ref _lastModifiedBy, value, "LastModifiedBy");
}
private bool _localOnly = false;
[Browsable(false)]
[ReadOnly(true)]
public bool LocalOnly
{
get => _localOnly;
set => SetProperty(ref _localOnly, value, "LocalOnly");
}
private int _version = -1;
[Browsable(false)]
[ReadOnly(true)]
public int Version
{
get => _version;
set => SetProperty(ref _version, value, "Version");
}
public LabratoryDetailsDbRecord(ILabratoryDetailsDbRecord labratoryDetailsDbRecord)
{
Name = labratoryDetailsDbRecord.Name;
LabratoryName = labratoryDetailsDbRecord.LabratoryName;
LabratoryContactName = labratoryDetailsDbRecord.LabratoryContactName;
LabratoryContactPhone = labratoryDetailsDbRecord.LabratoryContactPhone;
LabratoryContactFax = labratoryDetailsDbRecord.LabratoryContactFax;
LabratoryContactEmail = labratoryDetailsDbRecord.LabratoryContactEmail;
LabratoryTestRefNumber = labratoryDetailsDbRecord.LabratoryTestRefNumber;
LabratoryProjectRefNumber = labratoryDetailsDbRecord.LabratoryProjectRefNumber;
LastModified = labratoryDetailsDbRecord.LastModified;
LastModifiedBy = labratoryDetailsDbRecord.LastModifiedBy;
LocalOnly = labratoryDetailsDbRecord.LocalOnly;
Version = labratoryDetailsDbRecord.Version;
}
public LabratoryDetailsDbRecord() { }
public LabratoryDetailsDbRecord(IDataReader reader)
{
Name = Utility.GetString(reader, "Name");
LabratoryName = Utility.GetString(reader, "LabratoryName");
LabratoryContactName = Utility.GetString(reader, "LabratoryContactName");
LabratoryContactPhone = Utility.GetString(reader, "LabratoryContactPhone");
LabratoryContactFax = Utility.GetString(reader, "LabratoryContactFax");
LabratoryContactEmail = Utility.GetString(reader, "LabratoryContactEmail");
LabratoryTestRefNumber = Utility.GetString(reader, "LabratoryTestRefNumber");
LabratoryProjectRefNumber = Utility.GetString(reader, "LabratoryProjectRefNumber");
LastModified = Utility.GetDateTime(reader, "LastModified", DateTime.MinValue);
LastModifiedBy = Utility.GetString(reader, "LastModifiedBy");
LocalOnly = Utility.GetBool(reader, "LocalOnly");
Version = Utility.GetInt(reader, "Version");
}
public bool IsInvalidBlank()
{
return string.IsNullOrWhiteSpace(Name);
}
}
}

Some files were not shown because too many files have changed in this diff Show More