init
This commit is contained in:
55
Common/DTS.Common/Classes/BulkObservableCollection.cs
Normal file
55
Common/DTS.Common/Classes/BulkObservableCollection.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
188
Common/DTS.Common/Classes/ChannelCodes/ChannelCode.cs
Normal file
188
Common/DTS.Common/Classes/ChannelCodes/ChannelCode.cs
Normal 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);
|
||||
}
|
||||
22
Common/DTS.Common/Classes/ChannelCodes/TextPastedArgs.cs
Normal file
22
Common/DTS.Common/Classes/ChannelCodes/TextPastedArgs.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
Common/DTS.Common/Classes/ClockSync/ClockSyncProfile.cs
Normal file
57
Common/DTS.Common/Classes/ClockSync/ClockSyncProfile.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Common/DTS.Common/Classes/ClockSync/IClockSyncProfile.cs
Normal file
14
Common/DTS.Common/Classes/ClockSync/IClockSyncProfile.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.Common.Classes.Connection
|
||||
{
|
||||
public class NotConnectedException : ApplicationException
|
||||
{
|
||||
public NotConnectedException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
80
Common/DTS.Common/Classes/DASFactory/CanDiagnostics.cs
Normal file
80
Common/DTS.Common/Classes/DASFactory/CanDiagnostics.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
Common/DTS.Common/Classes/DASFactory/DiagnosticMessageRow.cs
Normal file
22
Common/DTS.Common/Classes/DASFactory/DiagnosticMessageRow.cs
Normal 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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
45
Common/DTS.Common/Classes/DASFactory/TCDiagnosticResult.cs
Normal file
45
Common/DTS.Common/Classes/DASFactory/TCDiagnosticResult.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
242
Common/DTS.Common/Classes/DASFactory/TMSNConfig.cs
Normal file
242
Common/DTS.Common/Classes/DASFactory/TMSNConfig.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
Common/DTS.Common/Classes/DASFactory/TemperatureConfig.cs
Normal file
116
Common/DTS.Common/Classes/DASFactory/TemperatureConfig.cs
Normal 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}");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
31
Common/DTS.Common/Classes/DSP/DASRestriction.cs
Normal file
31
Common/DTS.Common/Classes/DSP/DASRestriction.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
115
Common/DTS.Common/Classes/DSP/DSPFilterCollection.cs
Normal file
115
Common/DTS.Common/Classes/DSP/DSPFilterCollection.cs
Normal 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
70
Common/DTS.Common/Classes/DSP/DSPFilterConverter.cs
Normal file
70
Common/DTS.Common/Classes/DSP/DSPFilterConverter.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Common/DTS.Common/Classes/DSP/DSPFilterRestriction.cs
Normal file
31
Common/DTS.Common/Classes/DSP/DSPFilterRestriction.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
121
Common/DTS.Common/Classes/DSP/DSPFilterType.cs
Normal file
121
Common/DTS.Common/Classes/DSP/DSPFilterType.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Common/DTS.Common/Classes/DSP/IStreamingFilterProfile.cs
Normal file
34
Common/DTS.Common/Classes/DSP/IStreamingFilterProfile.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
18
Common/DTS.Common/Classes/DSP/ScalerAttribute.cs
Normal file
18
Common/DTS.Common/Classes/DSP/ScalerAttribute.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
Common/DTS.Common/Classes/DSP/StreamingFilterConverter.cs
Normal file
70
Common/DTS.Common/Classes/DSP/StreamingFilterConverter.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
82
Common/DTS.Common/Classes/DSP/StreamingFilterProfile.cs
Normal file
82
Common/DTS.Common/Classes/DSP/StreamingFilterProfile.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
445
Common/DTS.Common/Classes/DTS.Viewer/TestMetadata/TestChannel.cs
Normal file
445
Common/DTS.Common/Classes/DTS.Viewer/TestMetadata/TestChannel.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
9
Common/DTS.Common/Classes/GroupTemplates/Constants.cs
Normal file
9
Common/DTS.Common/Classes/GroupTemplates/Constants.cs
Normal 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_";
|
||||
}
|
||||
}
|
||||
157
Common/DTS.Common/Classes/Groups/ChannelDbRecord.cs
Normal file
157
Common/DTS.Common/Classes/Groups/ChannelDbRecord.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
5477
Common/DTS.Common/Classes/Groups/GroupChannel.cs
Normal file
5477
Common/DTS.Common/Classes/Groups/GroupChannel.cs
Normal file
File diff suppressed because it is too large
Load Diff
78
Common/DTS.Common/Classes/Groups/GroupDbRecord.cs
Normal file
78
Common/DTS.Common/Classes/Groups/GroupDbRecord.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
85
Common/DTS.Common/Classes/Groups/GroupGRPImportChannel.cs
Normal file
85
Common/DTS.Common/Classes/Groups/GroupGRPImportChannel.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Common/DTS.Common/Classes/Groups/GroupGRPImportError.cs
Normal file
35
Common/DTS.Common/Classes/Groups/GroupGRPImportError.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Common/DTS.Common/Classes/Groups/GroupGRPImportGroup.cs
Normal file
42
Common/DTS.Common/Classes/Groups/GroupGRPImportGroup.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
64
Common/DTS.Common/Classes/Groups/GroupHardwareDbRecord.cs
Normal file
64
Common/DTS.Common/Classes/Groups/GroupHardwareDbRecord.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
236
Common/DTS.Common/Classes/Groups/GroupHelper.cs
Normal file
236
Common/DTS.Common/Classes/Groups/GroupHelper.cs
Normal 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
|
||||
}
|
||||
}
|
||||
86
Common/DTS.Common/Classes/Groups/TestSetupGroupRecord.cs
Normal file
86
Common/DTS.Common/Classes/Groups/TestSetupGroupRecord.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
218
Common/DTS.Common/Classes/Hardware/DASChannelDBRecord.cs
Normal file
218
Common/DTS.Common/Classes/Hardware/DASChannelDBRecord.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
201
Common/DTS.Common/Classes/Hardware/DASDBRecord.cs
Normal file
201
Common/DTS.Common/Classes/Hardware/DASDBRecord.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
359
Common/DTS.Common/Classes/Hardware/DASMonitorInfo.cs
Normal file
359
Common/DTS.Common/Classes/Hardware/DASMonitorInfo.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Common/DTS.Common/Classes/Hardware/DragAndDropPayload.cs
Normal file
9
Common/DTS.Common/Classes/Hardware/DragAndDropPayload.cs
Normal 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";
|
||||
}
|
||||
}
|
||||
11
Common/DTS.Common/Classes/Hardware/ExternalTilt.cs
Normal file
11
Common/DTS.Common/Classes/Hardware/ExternalTilt.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
45
Common/DTS.Common/Classes/Hardware/SerializableAAF.cs
Normal file
45
Common/DTS.Common/Classes/Hardware/SerializableAAF.cs
Normal 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);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
202
Common/DTS.Common/Classes/ISO/IsoCode.cs
Normal file
202
Common/DTS.Common/Classes/ISO/IsoCode.cs
Normal 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]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Common/DTS.Common/Classes/ImportData.cs
Normal file
53
Common/DTS.Common/Classes/ImportData.cs
Normal 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>();
|
||||
|
||||
}
|
||||
}
|
||||
36
Common/DTS.Common/Classes/Locking/LockError.cs
Normal file
36
Common/DTS.Common/Classes/Locking/LockError.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
30
Common/DTS.Common/Classes/Locking/LockRecord.cs
Normal file
30
Common/DTS.Common/Classes/Locking/LockRecord.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
191
Common/DTS.Common/Classes/Locking/SensorsLocking.cs
Normal file
191
Common/DTS.Common/Classes/Locking/SensorsLocking.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
55
Common/DTS.Common/Classes/RegionNames.cs
Normal file
55
Common/DTS.Common/Classes/RegionNames.cs
Normal 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";
|
||||
}
|
||||
}
|
||||
790
Common/DTS.Common/Classes/Sensors/AnalogDbRecord.cs
Normal file
790
Common/DTS.Common/Classes/Sensors/AnalogDbRecord.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
130
Common/DTS.Common/Classes/Sensors/CANRecord.cs
Normal file
130
Common/DTS.Common/Classes/Sensors/CANRecord.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Common/DTS.Common/Classes/Sensors/CalMode.cs
Normal file
65
Common/DTS.Common/Classes/Sensors/CalMode.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
520
Common/DTS.Common/Classes/Sensors/CalibrationRecord.cs
Normal file
520
Common/DTS.Common/Classes/Sensors/CalibrationRecord.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Common/DTS.Common/Classes/Sensors/ChannelSerialNumber.cs
Normal file
23
Common/DTS.Common/Classes/Sensors/ChannelSerialNumber.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Common/DTS.Common/Classes/Sensors/ChannelTypeUtility.cs
Normal file
41
Common/DTS.Common/Classes/Sensors/ChannelTypeUtility.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
320
Common/DTS.Common/Classes/Sensors/DigitalInDbRecord.cs
Normal file
320
Common/DTS.Common/Classes/Sensors/DigitalInDbRecord.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
131
Common/DTS.Common/Classes/Sensors/DigitalInputScaleMultiplier.cs
Normal file
131
Common/DTS.Common/Classes/Sensors/DigitalInputScaleMultiplier.cs
Normal 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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
180
Common/DTS.Common/Classes/Sensors/DigitalOutDbRecord.cs
Normal file
180
Common/DTS.Common/Classes/Sensors/DigitalOutDbRecord.cs
Normal 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"];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
634
Common/DTS.Common/Classes/Sensors/FilterClass.cs
Normal file
634
Common/DTS.Common/Classes/Sensors/FilterClass.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
404
Common/DTS.Common/Classes/Sensors/InitialOffset.cs
Normal file
404
Common/DTS.Common/Classes/Sensors/InitialOffset.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
699
Common/DTS.Common/Classes/Sensors/LinearizationFormula.cs
Normal file
699
Common/DTS.Common/Classes/Sensors/LinearizationFormula.cs
Normal 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),
|
||||
};
|
||||
}*/
|
||||
}
|
||||
}
|
||||
113
Common/DTS.Common/Classes/Sensors/ParseParameters.cs
Normal file
113
Common/DTS.Common/Classes/Sensors/ParseParameters.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
216
Common/DTS.Common/Classes/Sensors/SensorCalDbRecord.cs
Normal file
216
Common/DTS.Common/Classes/Sensors/SensorCalDbRecord.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Common/DTS.Common/Classes/Sensors/SensorDbRecord.cs
Normal file
38
Common/DTS.Common/Classes/Sensors/SensorDbRecord.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
316
Common/DTS.Common/Classes/Sensors/SquibDbRecord.cs
Normal file
316
Common/DTS.Common/Classes/Sensors/SquibDbRecord.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
98
Common/DTS.Common/Classes/Sensors/StreamInputRecord.cs
Normal file
98
Common/DTS.Common/Classes/Sensors/StreamInputRecord.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
212
Common/DTS.Common/Classes/Sensors/StreamOutputRecord.cs
Normal file
212
Common/DTS.Common/Classes/Sensors/StreamOutputRecord.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
84
Common/DTS.Common/Classes/Sensors/ThermocouplerRecord.cs
Normal file
84
Common/DTS.Common/Classes/Sensors/ThermocouplerRecord.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
137
Common/DTS.Common/Classes/Sensors/UARTRecord.cs
Normal file
137
Common/DTS.Common/Classes/Sensors/UARTRecord.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
304
Common/DTS.Common/Classes/Sensors/ZeroMethod.cs
Normal file
304
Common/DTS.Common/Classes/Sensors/ZeroMethod.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
Common/DTS.Common/Classes/Sensors/ZeroRef.cs
Normal file
52
Common/DTS.Common/Classes/Sensors/ZeroRef.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
Common/DTS.Common/Classes/ServiceCall.cs
Normal file
117
Common/DTS.Common/Classes/ServiceCall.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
60
Common/DTS.Common/Classes/Singleton.cs
Normal file
60
Common/DTS.Common/Classes/Singleton.cs
Normal 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<MySingleton>).</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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Common/DTS.Common/Classes/StatusAndProgressBarEventArgs.cs
Normal file
16
Common/DTS.Common/Classes/StatusAndProgressBarEventArgs.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
363
Common/DTS.Common/Classes/TMAT/TMTBase.cs
Normal file
363
Common/DTS.Common/Classes/TMAT/TMTBase.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
85
Common/DTS.Common/Classes/TMAT/TmtSingleFile.cs
Normal file
85
Common/DTS.Common/Classes/TMAT/TmtSingleFile.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
102
Common/DTS.Common/Classes/TMAT/TmtSplitFiles.cs
Normal file
102
Common/DTS.Common/Classes/TMAT/TmtSplitFiles.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
248
Common/DTS.Common/Classes/TagAwareBase.cs
Normal file
248
Common/DTS.Common/Classes/TagAwareBase.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
373
Common/DTS.Common/Classes/Tags.cs
Normal file
373
Common/DTS.Common/Classes/Tags.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
63
Common/DTS.Common/Classes/Tags/Tag.cs
Normal file
63
Common/DTS.Common/Classes/Tags/Tag.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Common/DTS.Common/Classes/Tags/TagAssignment.cs
Normal file
37
Common/DTS.Common/Classes/Tags/TagAssignment.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
162
Common/DTS.Common/Classes/Tags/TagAwareBase.cs
Normal file
162
Common/DTS.Common/Classes/Tags/TagAwareBase.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
250
Common/DTS.Common/Classes/Tags/TagsInstance.cs
Normal file
250
Common/DTS.Common/Classes/Tags/TagsInstance.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user