using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using DTS.Common.ICommunication; using DTS.Common.Utilities.Logging; using DTS.Common.Events; using DTS.Common.Strings; using DTS.Common.Interface.DASFactory; namespace DTS.DASLib.Command.TDAS { internal class SetupChannelLoadCommandString : CommandString { internal const double PRO_MAX_SHUNT_EM_CURRENT_MA = 2.4; internal const double G5_MAX_SHUNT_EM_CURRENT_MA = 1.0; internal const double PRO_MAX_SHUNT_EM_VOLTAGE_MV = 1000.0; internal const double G5_MAX_SHUNT_EM_VOLTAGE_MV = 1000.0; internal const double DEFAULT_SHUNT_EM_PERCENT = 0.8; /// /// following code is roughly copied from same named function in TDC, in tdas_ZeroCal.c /// returns a string representing the adjusted shunt expected value, which is affected by /// gain and current limits. /// /// /// /// /// /// /// internal string GetShuntValueString(double gain, int shuntPosition, double actualInputRangemV, out int targetADC, bool bIsG5) { double dMaximumShuntEmulationCurrent; double dMaxShuntVoltageMv; if (bIsG5) { dMaximumShuntEmulationCurrent = G5_MAX_SHUNT_EM_CURRENT_MA; actualInputRangemV = 2500 / gain; dMaxShuntVoltageMv = G5_MAX_SHUNT_EM_VOLTAGE_MV; } else { dMaximumShuntEmulationCurrent = PRO_MAX_SHUNT_EM_CURRENT_MA; actualInputRangemV = 5000 / gain; dMaxShuntVoltageMv = PRO_MAX_SHUNT_EM_VOLTAGE_MV; } var dMaxShuntEmMv = Math.Min(dMaxShuntVoltageMv, dMaximumShuntEmulationCurrent * shuntPosition * 0.5D); var dShuntEmPerc = DEFAULT_SHUNT_EM_PERCENT; var dShuntEmMv = dShuntEmPerc * actualInputRangemV; if (dShuntEmMv > dMaxShuntEmMv) { dShuntEmPerc = dMaxShuntEmMv / actualInputRangemV; if (0.1 > dShuntEmPerc) { dShuntEmPerc = 0.05; } targetADC = Convert.ToInt32(0.5D + Common.Constants.ADC_MIDPOINT * dShuntEmPerc); return $"{shuntPosition}%{(dShuntEmPerc * 100.0).ToString(System.Globalization.CultureInfo.InvariantCulture)}"; } targetADC = 26214; // 80% of ADC return $"{shuntPosition}"; } public char Channel { get; set; } = '1'; public char ChannelType { get; set; } = 'F'; public char FilterOption { get; set; } = 'F'; public char OffsetOption { get; set; } = 'Y'; public char ShuntMode { get; set; } = 'E'; public char[] ExcitationSetting { get; set; } = { '5' }; public char[] Gain { get; set; } = { '1', '.', '0' }; public char[] EquivalentShuntInEU { get; set; } = { '1', '.', '0' }; public char[] Sensitivity { get; set; } = { '1', '.', '0' }; public char SensitivityUnit { get; set; } = 'E'; public char[] EUString { get; set; } = { 'N', 'o', 'E', 'U' }; public char[] ChannelNumber { get; set; } = { '0', '0', '0', '0' }; public char[] Location { get; set; } = { 'N', 'o', 'L', 'o', 'c' }; public int ShuntPosition { get; set; } = 350; public double ActualRange { get; set; } = 0; public bool IsG5 { get; set; } = true; public int TargetADC { get; private set; } protected override string _CommandDescription => "SetupChaneLoad - SCL"; protected override string _CommandString => "SCL"; public override byte[] GetParameters() { var ms = new System.IO.MemoryStream(); ms.WriteByte(Convert.ToByte(' ')); ms.WriteByte(Convert.ToByte(Channel)); ms.WriteByte(Convert.ToByte(' ')); ms.WriteByte(Convert.ToByte(ChannelType)); ms.WriteByte(Convert.ToByte(FilterOption)); ms.WriteByte(Convert.ToByte(OffsetOption)); ms.WriteByte(Convert.ToByte(ShuntMode)); ms.WriteByte(Convert.ToByte(' ')); foreach (var c in ExcitationSetting) { ms.WriteByte(Convert.ToByte(c)); } ms.WriteByte(Convert.ToByte(' ')); foreach (var c in Gain) { ms.WriteByte(Convert.ToByte(c)); } ms.WriteByte(Convert.ToByte(' ')); var dGain = double.Parse(new string(Gain), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); var s = GetShuntValueString(dGain, ShuntPosition, ActualRange, out int iTargetADC, IsG5); TargetADC = iTargetADC; foreach (var c in s) { ms.WriteByte(Convert.ToByte(c)); } return ms.ToArray(); } public SetupChannelLoadCommandString(bool bIsG5) { IsG5 = bIsG5; RackCommand = false; } } public class SetupChannelLoad : CommandBase { private SetupChannelLoadCommandString _commandString { get { var basePacket = baseCommand as TDASCommandPacketBase; return basePacket?.GetCommandStringObject(0) as SetupChannelLoadCommandString; } } public int Channel { get => int.Parse(new string(_commandString.Channel, 1)); set { if (value < 0 || value > 8) { throw new Exception("channel must be between 1 and 8"); } _commandString.Channel = value.ToString()[0]; } } public enum ChannelTypes { FullBridge, HalfBridge, Diagnostic }; public ChannelTypes ChannelType { get { switch (_commandString.ChannelType) { case 'F': return ChannelTypes.FullBridge; case 'H': return ChannelTypes.HalfBridge; case 'D': return ChannelTypes.Diagnostic; default: throw new Exception("unknown channel type " + _commandString.ChannelType); } } set { switch (value) { case ChannelTypes.Diagnostic: _commandString.ChannelType = 'D'; break; case ChannelTypes.FullBridge: _commandString.ChannelType = 'F'; break; case ChannelTypes.HalfBridge: _commandString.ChannelType = 'H'; break; default: throw new Exception("Unknown channel type : " + value); } } } public enum FilterOptions { Filter, BypassFilter }; public FilterOptions FilterOption { get { switch (_commandString.FilterOption) { case 'F': return FilterOptions.Filter; case 'B': return FilterOptions.BypassFilter; default: throw new Exception("unknown FilterOption " + _commandString.FilterOption); } } set { switch (value) { case FilterOptions.Filter: _commandString.FilterOption = 'F'; break; case FilterOptions.BypassFilter: _commandString.FilterOption = 'B'; break; default: throw new Exception("unknown FilterOption " + value); } } } public enum OffsetOptions { AutoOffset, DoNotOffset }; public OffsetOptions OffsetOption { get { switch (_commandString.OffsetOption) { case 'Y': return OffsetOptions.AutoOffset; case 'N': return OffsetOptions.DoNotOffset; default: throw new Exception("unknown OffsetOption " + _commandString.OffsetOption); } } set { switch (value) { case OffsetOptions.DoNotOffset: _commandString.OffsetOption = 'N'; break; case OffsetOptions.AutoOffset: _commandString.OffsetOption = 'Y'; break; default: throw new Exception("unknown OffsetOption " + value); } } } public enum ShuntModes { ShuntResistance, EmulateShunt, None }; public ShuntModes ShuntMode { get { switch (_commandString.ShuntMode) { case 'S': return ShuntModes.ShuntResistance; case 'E': return ShuntModes.EmulateShunt; case 'N': return ShuntModes.None; default: throw new Exception("unknown ShuntMode " + _commandString.ShuntMode); } } set { switch (value) { case ShuntModes.None: _commandString.ShuntMode = 'N'; break; case ShuntModes.EmulateShunt: _commandString.ShuntMode = 'E'; break; case ShuntModes.ShuntResistance: _commandString.ShuntMode = 'S'; break; default: throw new Exception("unknown ShuntMode " + value); } } } public double ExcitationSetting { get => Convert.ToDouble(int.Parse(new string(_commandString.ExcitationSetting))); set { switch (value) { case 0D: _commandString.ExcitationSetting = new[] { '0' }; break; case 2D: _commandString.ExcitationSetting = new[] { '2' }; break; case 5D: _commandString.ExcitationSetting = new[] { '5' }; break; case 10D: _commandString.ExcitationSetting = new[] { '1', '0' }; break; default: throw new Exception("Excitation must be 0, 2, 5, or 10 - requested was " + value); } } } public double Gain { get => double.Parse(new string(_commandString.Gain), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); set => _commandString.Gain = value.ToString("F1", System.Globalization.CultureInfo.InvariantCulture).ToCharArray(); } /// /// 1 - 7 = shunt positions, or bridge resistance for emulation /// public int ShuntPosition { get => _commandString.ShuntPosition; set => _commandString.ShuntPosition = value; } /// /// equivalent shunt value in EU (version 2 parameter) /// public double ShuntEUValue { get => double.Parse(new string(_commandString.EquivalentShuntInEU)); set => _commandString.EquivalentShuntInEU = value.ToString("F6").ToCharArray(); } /// /// either in mV/V/EU or mv/EU (determined by Sensitivity Units) /// public double Sensitivity { get => double.Parse(new string(_commandString.Sensitivity)); set => _commandString.Sensitivity = value.ToString("F6").ToCharArray(); } /// /// command only supports V (mV/V/EU) or E(mV/EU) /// public enum SensitivityUnits { Volts, EngineeringUnits }; public SensitivityUnits SensitivityUnit { get { switch (_commandString.SensitivityUnit) { case 'V': return SensitivityUnits.Volts; case 'E': return SensitivityUnits.EngineeringUnits; default: throw new Exception("Unknown SensitivityUnit " + _commandString.SensitivityUnit); } } set { switch (value) { case SensitivityUnits.EngineeringUnits: _commandString.SensitivityUnit = 'E'; break; case SensitivityUnits.Volts: _commandString.SensitivityUnit = 'V'; break; default: throw new Exception("unknown SensitivityUnit " + value); } } } /// /// engineering units description - arbitrary string, max of 16 characters, spaces valid within quotes /// public string EUUnit { get => new string(_commandString.EUString); set { if (value.Length > 16) { throw new Exception("EU Units must be than 16 characters"); } if (value.Contains(' ') && !value.Contains('\"')) { throw new Exception("spaces must be within quotes"); } _commandString.EUString = value.ToCharArray(); } } public string ChannelNumber { get => new string(_commandString.ChannelNumber); set { if (value.Length > 4) { throw new Exception("Channel number must be 4 characters or less"); } if (value.Contains(' ') && !value.Contains('\"')) { throw new Exception("spaces must be within quotes"); } _commandString.ChannelNumber = value.ToCharArray(); } } public string Location { get => new string(_commandString.Location); set { if (value.Length > 16) { throw new Exception("Location must be less than 16 characters"); } if (value.Contains(' ') && !value.Contains('\"')) { throw new Exception("spaces must be within quotes"); } _commandString.Location = value.ToCharArray(); } } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } private SetupChannelLoadCommandString _cs; public SetupChannelLoad(DTS.Common.Interface.DASFactory.ICommunication sock, bool isG5) : base(sock) { _cs = new SetupChannelLoadCommandString(isG5); var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public SetupChannelLoad(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout, bool isG5) : base(sock, msTimeout) { _cs = new SetupChannelLoadCommandString(isG5); var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public int TargetADC => _cs.TargetADC; protected override void ProcessData() { base.ProcessData(); if (IsErrored()) { throw new Exception("SetupChannelLoad failed - " + ResponseData); } } } // CLH 6/19/2017 internal class SetupChannelLoadBroadcastCommandString : CommandString { internal const double PRO_MAX_SHUNT_EM_CURRENT_MA = 2.4; internal const double G5_MAX_SHUNT_EM_CURRENT_MA = 1.0; internal const double PRO_MAX_SHUNT_EM_VOLTAGE_MV = 1000.0; internal const double G5_MAX_SHUNT_EM_VOLTAGE_MV = 1000.0; internal const double DEFAULT_SHUNT_EM_PERCENT = 0.8; /// /// following code is roughly copied from same named function in TDC, in tdas_ZeroCal.c /// returns a string representing the adjusted shunt expected value, which is affected by /// gain and current limits. /// /// /// internal string GetShuntValueString(double dGain, int iShuntPosition, double dActualInputRangeMV, out int iTargetADC, bool bIsG5) { double dMaximumShuntEmulationCurrent = 0D; double dMaxShuntVoltageMV = 0D; if (bIsG5) { dMaximumShuntEmulationCurrent = G5_MAX_SHUNT_EM_CURRENT_MA; dActualInputRangeMV = 2500 / dGain; dMaxShuntVoltageMV = G5_MAX_SHUNT_EM_VOLTAGE_MV; } else { dMaximumShuntEmulationCurrent = PRO_MAX_SHUNT_EM_CURRENT_MA; dActualInputRangeMV = 5000 / dGain; dMaxShuntVoltageMV = PRO_MAX_SHUNT_EM_VOLTAGE_MV; } double dMaxShuntEmMV = System.Math.Min(dMaxShuntVoltageMV, dMaximumShuntEmulationCurrent * (double)iShuntPosition * 0.5D); double dShuntEmPerc = DEFAULT_SHUNT_EM_PERCENT; double dShuntEmMV = dShuntEmPerc * dActualInputRangeMV; if (dShuntEmMV > dMaxShuntEmMV) { dShuntEmPerc = dMaxShuntEmMV / dActualInputRangeMV; if (0.1 > dShuntEmPerc) { dShuntEmPerc = 0.05; } iTargetADC = Convert.ToInt32(0.5D + 32767D * dShuntEmPerc); return string.Format("{0}%{1}", iShuntPosition, (dShuntEmPerc * 100.0).ToString(System.Globalization.CultureInfo.InvariantCulture)); } else { iTargetADC = 26214; // 80% of ADC return string.Format("{0}", iShuntPosition); } } private char _channel = '1'; public char Channel { get { return _channel; } set { _channel = value; } } private char _channelType = 'F'; public char ChannelType { get { return _channelType; } set { _channelType = value; } } private char _filterOption = 'F'; public char FilterOption { get { return _filterOption; } set { _filterOption = value; } } private char _offsetOption = 'Y'; public char OffsetOption { get { return _offsetOption; } set { _offsetOption = value; } } private char _shuntMode = 'E'; public char ShuntMode { get { return _shuntMode; } set { _shuntMode = value; } } private char[] _excitationSetting = new char[] { '5' }; public char[] ExcitationSetting { get { return _excitationSetting; } set { _excitationSetting = value; } } private char[] _gain = new char[] { '1', '.', '0' }; public char[] Gain { get { return _gain; } set { _gain = value; } } private char[] _equivalentShuntInEU = new char[] { '1', '.', '0' }; public char[] EquivalentShuntInEU { get { return _equivalentShuntInEU; } set { _equivalentShuntInEU = value; } } private char[] _sensitivity = new char[] { '1', '.', '0' }; public char[] Sensitivity { get { return _sensitivity; } set { _sensitivity = value; } } private char _sensitivityUnit = 'E'; public char SensitivityUnit { get { return _sensitivityUnit; } set { _sensitivityUnit = value; } } private char[] _euString = new char[] { 'N', 'o', 'E', 'U' }; public char[] EUString { get { return _euString; } set { _euString = value; } } private char[] _channelNumber = new char[] { '0', '0', '0', '0' }; public char[] ChannelNumber { get { return _channelNumber; } set { _channelNumber = value; } } private char[] _location = new char[] { 'N', 'o', 'L', 'o', 'c' }; public char[] Location { get { return _location; } set { _location = value; } } private int _iShuntPosition = 350; public int iShuntPosition { get { return _iShuntPosition; } set { _iShuntPosition = value; } } private double _actualRange = 0; public double ActualRange { get { return _actualRange; } set { _actualRange = value; } } private bool _isG5 = true; public bool IsG5 { get { return _isG5; } set { _isG5 = value; } } private int _TargetADC = 0; public int TargetADC { get { return _TargetADC; } } private int _moduleIndex = 0; public int ModuleIndex { get { return _moduleIndex; } set { _moduleIndex = value; } } protected override string _CommandDescription { get { return "SetupChaneLoad - SCL (*)"; } } protected override string _CommandString { get { if (ModuleIndex >= 0) { return string.Format("*{0}SCL", ModuleIndex); } else { return "*SCL"; } } } public override byte[] GetParameters() { System.IO.MemoryStream ms = new System.IO.MemoryStream(); ms.WriteByte(Convert.ToByte(' ')); ms.WriteByte(Convert.ToByte(_channel)); ms.WriteByte(Convert.ToByte(' ')); ms.WriteByte(Convert.ToByte(_channelType)); ms.WriteByte(Convert.ToByte(_filterOption)); ms.WriteByte(Convert.ToByte(_offsetOption)); ms.WriteByte(Convert.ToByte(_shuntMode)); ms.WriteByte(Convert.ToByte(' ')); foreach (char c in _excitationSetting) { ms.WriteByte(Convert.ToByte(c)); } ms.WriteByte(Convert.ToByte(' ')); foreach (char c in _gain) { ms.WriteByte(Convert.ToByte(c)); } ms.WriteByte(Convert.ToByte(' ')); double dGain = double.Parse(new string(_gain), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); int iTargetADC; string s = GetShuntValueString(dGain, iShuntPosition, ActualRange, out iTargetADC, IsG5); _TargetADC = iTargetADC; foreach (char c in s) { ms.WriteByte(Convert.ToByte(c)); } return ms.ToArray(); } public SetupChannelLoadBroadcastCommandString(bool bIsG5, int moduleIndex) { _moduleIndex = moduleIndex; IsG5 = bIsG5; RackCommand = false; } } public class SetupChannelLoadBroadcast : CommandBase { private SetupChannelLoadBroadcastCommandString _commandString { get { TDASCommandPacketBase basePacket = baseCommand as TDASCommandPacketBase; return basePacket.GetCommandStringObject(0) as SetupChannelLoadBroadcastCommandString; } } public int Channel { get { return int.Parse(new string(_commandString.Channel, 1)); } set { if (value < 0 || value > 8) { throw new Exception("channel must be between 1 and 8"); } _commandString.Channel = value.ToString()[0]; } } //public enum ChannelTypes { FullBridge, HalfBridge, Diagnostic }; public SetupChannelLoad.ChannelTypes ChannelType { get { switch (_commandString.ChannelType) { case 'F': return SetupChannelLoad.ChannelTypes.FullBridge; case 'H': return SetupChannelLoad.ChannelTypes.HalfBridge; case 'D': return SetupChannelLoad.ChannelTypes.Diagnostic; default: throw new Exception("unknown channel type " + _commandString.ChannelType.ToString()); } } set { switch (value) { case SetupChannelLoad.ChannelTypes.Diagnostic: _commandString.ChannelType = 'D'; break; case SetupChannelLoad.ChannelTypes.FullBridge: _commandString.ChannelType = 'F'; break; case SetupChannelLoad.ChannelTypes.HalfBridge: _commandString.ChannelType = 'H'; break; default: throw new Exception("Unknown channel type : " + value.ToString()); } } } //public enum FilterOptions { Filter, BypassFilter }; public SetupChannelLoad.FilterOptions FilterOption { get { switch (_commandString.FilterOption) { case 'F': return SetupChannelLoad.FilterOptions.Filter; case 'B': return SetupChannelLoad.FilterOptions.BypassFilter; default: throw new Exception("unknown FilterOption " + _commandString.FilterOption.ToString()); } } set { switch (value) { case SetupChannelLoad.FilterOptions.Filter: _commandString.FilterOption = 'F'; break; case SetupChannelLoad.FilterOptions.BypassFilter: _commandString.FilterOption = 'B'; break; default: throw new Exception("unknown FilterOption " + value.ToString()); } } } //public enum OffsetOptions { AutoOffset, DoNotOffset }; public SetupChannelLoad.OffsetOptions OffsetOption { get { switch (_commandString.OffsetOption) { case 'Y': return SetupChannelLoad.OffsetOptions.AutoOffset; case 'N': return SetupChannelLoad.OffsetOptions.DoNotOffset; default: throw new Exception("unknown OffsetOption " + _commandString.OffsetOption.ToString()); } } set { switch (value) { case SetupChannelLoad.OffsetOptions.DoNotOffset: _commandString.OffsetOption = 'N'; break; case SetupChannelLoad.OffsetOptions.AutoOffset: _commandString.OffsetOption = 'Y'; break; default: throw new Exception("unknown OffsetOption " + value.ToString()); } } } //public enum ShuntModes { ShuntResistance, EmulateShunt, None }; public SetupChannelLoad.ShuntModes ShuntMode { get { switch (_commandString.ShuntMode) { case 'S': return SetupChannelLoad.ShuntModes.ShuntResistance; case 'E': return SetupChannelLoad.ShuntModes.EmulateShunt; case 'N': return SetupChannelLoad.ShuntModes.None; default: throw new Exception("unknown ShuntMode " + _commandString.ShuntMode.ToString()); } } set { switch (value) { case SetupChannelLoad.ShuntModes.None: _commandString.ShuntMode = 'N'; break; case SetupChannelLoad.ShuntModes.EmulateShunt: _commandString.ShuntMode = 'E'; break; case SetupChannelLoad.ShuntModes.ShuntResistance: _commandString.ShuntMode = 'S'; break; default: throw new Exception("unknown ShuntMode " + value.ToString()); } } } public double ExcitationSetting { get { return Convert.ToDouble(int.Parse(new string(_commandString.ExcitationSetting))); } set { if (value == 0D) { _commandString.ExcitationSetting = new char[] { '0' }; } else if (value == 2D) { _commandString.ExcitationSetting = new char[] { '2' }; } else if (value == 5D) { _commandString.ExcitationSetting = new char[] { '5' }; } else if (value == 10D) { _commandString.ExcitationSetting = new char[] { '1', '0' }; } else { throw new Exception("Excitation must be 0, 2, 5, or 10 - requested was " + value.ToString()); } } } public double Gain { get { return double.Parse(new string(_commandString.Gain), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); } set { _commandString.Gain = string.Format("{0:0.0}", value).ToCharArray(); //_commandString.Gain = // value.ToString("G1", System.Globalization.CultureInfo.InvariantCulture).ToCharArray(); } } /// /// 1 - 7 = shunt positions, or bridge resistance for emulation /// public int ShuntPosition { get { return _commandString.iShuntPosition; } set { _commandString.iShuntPosition = value; } } /// /// equivalent shunt value in EU (version 2 parameter) /// public double ShuntEUValue { get { return double.Parse(new string(_commandString.EquivalentShuntInEU)); } set { _commandString.EquivalentShuntInEU = value.ToString("F6").ToCharArray(); } } /// /// either in mV/V/EU or mv/EU (determined by Sensitivity Units) /// public double Sensitivity { get { return double.Parse(new string(_commandString.Sensitivity)); } set { _commandString.Sensitivity = value.ToString("F6").ToCharArray(); } } /// /// command only supports V (mV/V/EU) or E(mV/EU) /// //public enum SensitivityUnits { Volts, EngineeringUnits }; public SetupChannelLoad.SensitivityUnits SensitivityUnit { get { switch (_commandString.SensitivityUnit) { case 'V': return SetupChannelLoad.SensitivityUnits.Volts; case 'E': return SetupChannelLoad.SensitivityUnits.EngineeringUnits; default: throw new Exception("Unknown SensitivityUnit " + _commandString.SensitivityUnit.ToString()); } } set { switch (value) { case SetupChannelLoad.SensitivityUnits.EngineeringUnits: _commandString.SensitivityUnit = 'E'; break; case SetupChannelLoad.SensitivityUnits.Volts: _commandString.SensitivityUnit = 'V'; break; default: throw new Exception("unknown SensitivityUnit " + value.ToString()); } } } /// /// engineering units description - arbitrary string, max of 16 characters, spaces valid within quotes /// public string EUUnit { get { return new string(_commandString.EUString); } set { if (value.Length > 16) { throw new Exception("EU Units must be than 16 characters"); } if (value.Contains(' ') && !value.Contains('\"')) { throw new Exception("spaces must be within quotes"); } _commandString.EUString = value.ToCharArray(); } } public string ChannelNumber { get { return new string(_commandString.ChannelNumber); } set { if (value.Length > 4) { throw new Exception("Channel number must be 4 characters or less"); } if (value.Contains(' ') && !value.Contains('\"')) { throw new Exception("spaces must be within quotes"); } _commandString.ChannelNumber = value.ToCharArray(); } } public string Location { get => new string(_commandString.Location); set { if (value.Length > 16) { throw new Exception("Location must be less than 16 characters"); } if (value.Contains(' ') && !value.Contains('\"')) { throw new Exception("spaces must be within quotes"); } _commandString.Location = value.ToCharArray(); } } private SetupChannelLoadBroadcastCommandString _cs; public SetupChannelLoadBroadcast(ICommunication sock, int moduleIndex, bool isG5) : base(sock) { _cs = new SetupChannelLoadBroadcastCommandString(isG5, moduleIndex); TDASCommandPacketBase command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; command.RackCommand = false; command.SingleModuleCommand = base.SingleModuleCommand; } public SetupChannelLoadBroadcast(ICommunication sock, int moduleIndex, int msTimeout, bool isG5) : base(sock, msTimeout) { _cs = new SetupChannelLoadBroadcastCommandString(isG5, moduleIndex); var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; command.RackCommand = false; command.SingleModuleCommand = base.SingleModuleCommand; } public int TargetADC => _cs.TargetADC; protected override void ProcessData() { base.ProcessData(); if (IsErrored()) { throw new Exception("SetupChannelLoad failed - " + ResponseData); } } } internal class SetupChannelReadCommandString : CommandString { public char Channel { get; set; } = '1'; protected override string _CommandDescription => "SetupChannelRead - SCR"; protected override string _CommandString => "SCR"; public override byte[] GetParameters() { var ms = new System.IO.MemoryStream(); ms.WriteByte(Convert.ToByte(' ')); ms.WriteByte(Convert.ToByte(Channel)); return ms.ToArray(); } } public class SetupChannelRead : CommandBase { private SetupChannelReadCommandString _commandString { get { var basePacket = baseCommand as TDASCommandPacketBase; return basePacket?.GetCommandStringObject(0) as SetupChannelReadCommandString; } } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } public int Channel { get => int.Parse(new string(_commandString.Channel, 1)); set { if (value < 0 || value > 8) { throw new Exception("channel must be between 1 and 8"); } _commandString.Channel = value.ToString()[0]; } } private double _excitation = double.NaN; public double Excitation { get { return _excitation; } } public double Gain { get; private set; } = double.NaN; private SetupChannelLoad.ChannelTypes _channelType; public SetupChannelLoad.ChannelTypes ChannelType { get { return _channelType; } } private SetupChannelLoad.FilterOptions _filterOptions; public SetupChannelLoad.FilterOptions FilterOptions { get { return _filterOptions; } } private SetupChannelLoad.OffsetOptions _offsetOption; public SetupChannelLoad.OffsetOptions OffsetOption { get { return _offsetOption; } } private SetupChannelLoad.ShuntModes _shuntMode; public SetupChannelLoad.ShuntModes ShuntMode { get { return _shuntMode; } } private readonly SetupChannelReadCommandString _cs = new SetupChannelReadCommandString(); public SetupChannelRead(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public SetupChannelRead(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public enum ResponseFields { chan = 0, options = 1, excitation = 2, gain = 3, shuntPosition = 4 } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf("SCR"); var end = s.LastIndexOf("\r\n"); if (start < 0 || end < start) { Gain = double.NaN; _excitation = double.NaN; return; } Debug.Assert(start >= 0 && end > start); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength); var data = ResponseData.Split(' '); for (var i = 0; i < data.Length; i++) { var field = (ResponseFields)i; switch (field) { case ResponseFields.options: { char[] options = data[i].ToCharArray(); switch (options[0]) { // channel type case 'F': _channelType = SetupChannelLoad.ChannelTypes.FullBridge; break; case 'H': _channelType = SetupChannelLoad.ChannelTypes.HalfBridge; break; case 'D': _channelType = SetupChannelLoad.ChannelTypes.Diagnostic; break; } switch (options[1]) { // filter case 'F': _filterOptions = SetupChannelLoad.FilterOptions.Filter; break; case 'B': _filterOptions = SetupChannelLoad.FilterOptions.BypassFilter; break; } switch (options[2]) { // offset case 'Y': _offsetOption = SetupChannelLoad.OffsetOptions.AutoOffset; break; case 'N': _offsetOption = SetupChannelLoad.OffsetOptions.DoNotOffset; break; } switch (options[3]) { // shunt case 'S': _shuntMode = SetupChannelLoad.ShuntModes.ShuntResistance; break; case 'E': _shuntMode = SetupChannelLoad.ShuntModes.EmulateShunt; break; case 'N': _shuntMode = SetupChannelLoad.ShuntModes.None; break; } break; } case ResponseFields.excitation: _excitation = Convert.ToDouble(data[i]); break; case ResponseFields.gain: Gain = double.Parse(data[i], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); break; } } } } internal class SetupChannelReadALLCommandString : CommandString { protected override string _CommandDescription { get { return "SetupChannelReadAll - SCR ALL"; } } protected override string _CommandString { get { return "SCR ALL"; } } public override byte[] GetParameters() { System.IO.MemoryStream ms = new System.IO.MemoryStream(); ms.WriteByte(Convert.ToByte(' ')); return ms.ToArray(); } } public class SetupChannelReadlAll : CommandBase { private SetupChannelReadALLCommandString _commandString { get { TDASCommandPacketBase command = baseCommand as TDASCommandPacketBase; return command.GetCommandStringObject(0) as SetupChannelReadALLCommandString; } } public int ModuleIndex { get { return (baseCommand as TDASCommandPacketBase).ModuleIndex; } set { (baseCommand as TDASCommandPacketBase).ModuleIndex = value; } } private Dictionary _gains = new Dictionary(); public double GetGain(int channel) { if (_gains.ContainsKey(channel)) { return _gains[channel]; } else { return double.NaN; } } private Dictionary _excitations = new Dictionary(); public double GetExcitation(int channel) { if (_excitations.ContainsKey(channel)) { return _excitations[channel]; } else { return double.NaN; } } public SetupChannelReadlAll(DTS.Common.Interface.DASFactory.ICommunication sock, int linesExpected) : base(sock) { TDASCommandPacketBase command = new TDASCommandPacketBase(new SetupChannelReadALLCommandString()); command.ExpectsMultipleLines = true; command.LinesExpected = linesExpected; command.SingleModuleCommand = base.SingleModuleCommand; baseCommand = command; command.RebuildBytes = true; } public SetupChannelReadlAll(DTS.Common.Interface.DASFactory.ICommunication sock, int linesExpected, int msTimeout) : base(sock, msTimeout) { TDASCommandPacketBase command = new TDASCommandPacketBase(new SetupChannelReadALLCommandString()); command.ExpectsMultipleLines = true; command.LinesExpected = linesExpected; command.SingleModuleCommand = base.SingleModuleCommand; baseCommand = command; command.RebuildBytes = true; } protected override void ProcessData() { TDASCommandPacketBase response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } string s = System.Text.ASCIIEncoding.ASCII.GetString(response.ToBytes()); string[] lines = s.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); _responseData = s; foreach (var line in lines) { int indexOfChecksum = line.IndexOf('~'); string sTemp = line; if (indexOfChecksum > 0) { sTemp = line.Substring(0, indexOfChecksum); } int start = sTemp.IndexOf("SCR:"); if (start < 0) { continue; } sTemp = sTemp.Substring(start + 4); sTemp = sTemp.Trim(); string[] data = sTemp.Split(' '); int channel = 0; for (int i = 0; i < data.Length; i++) { SetupChannelRead.ResponseFields field = (SetupChannelRead.ResponseFields)i; switch (field) { case SetupChannelRead.ResponseFields.chan: channel = int.Parse(data[i]); break; case SetupChannelRead.ResponseFields.excitation: _excitations[channel] = TDASNumberHelper.ParseDouble(data[i]); break; case SetupChannelRead.ResponseFields.gain: _gains[channel] = TDASNumberHelper.ParseDouble(data[i]); break; } } } } } // CLH calstation 2 purposes internal class ZeroAverageBroadcastCommandString : CommandString { private int _moduleIndex = 0; public int ModuleIndex { get { return _moduleIndex; } set { _moduleIndex = value; } } protected override string _CommandDescription { get { return "ZeroAverage - ZA (*)"; } } protected override string _CommandString { get { if (ModuleIndex >= 0) { return string.Format("*{0}ZA", ModuleIndex); } else { return "*ZA"; } } } public ZeroAverageBroadcastCommandString(int moduleIndex) { RackCommand = false; _moduleIndex = moduleIndex; } } public class ZeroAverageBroadcast : CommandBase { private ZeroAverageBroadcastCommandString _commandString { get { TDASCommandPacketBase basePacket = baseCommand as TDASCommandPacketBase; return basePacket.GetCommandStringObject(0) as ZeroAverageBroadcastCommandString; } } public ZeroAverageBroadcast(DTS.Common.Interface.DASFactory.ICommunication sock, int moduleIndex) : base(sock) { TDASCommandPacketBase command = new TDASCommandPacketBase(new ZeroAverageBroadcastCommandString(moduleIndex)); baseCommand = command; command.ExpectsData = false; command.RebuildBytes = true; command.RackCommand = false; command.SingleModuleCommand = base.SingleModuleCommand; } public ZeroAverageBroadcast(DTS.Common.Interface.DASFactory.ICommunication sock, int moduleIndex, int msTimeout) : base(sock, msTimeout) { TDASCommandPacketBase command = new TDASCommandPacketBase(new ZeroAverageBroadcastCommandString(moduleIndex)); baseCommand = command; command.ExpectsData = false; command.RebuildBytes = true; command.RackCommand = false; command.SingleModuleCommand = base.SingleModuleCommand; } protected override void ProcessData() { base.ProcessData(); } } internal class ZeroAverageCommandString : CommandString { public char Channel { get; set; } = '0'; protected override string _CommandDescription => "ZeroAverage - ZA"; protected override string _CommandString => "ZA"; public override byte[] GetParameters() { var ms = new System.IO.MemoryStream(); ms.WriteByte(Convert.ToByte(' ')); ms.WriteByte(Convert.ToByte(Channel)); return ms.ToArray(); } } public class ZeroAverage : CommandBase { private ZeroAverageCommandString _commandString { get { var basePacket = baseCommand as TDASCommandPacketBase; return basePacket?.GetCommandStringObject(0) as ZeroAverageCommandString; } } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } public int Channel { get => int.Parse(new string(_commandString.Channel, 1)); set { if (value < 0 || value > 8) { throw new Exception("channel must be between 1 and 8"); } _commandString.Channel = value.ToString()[0]; } } private readonly ZeroAverageCommandString _cs = new ZeroAverageCommandString(); public ZeroAverage(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public ZeroAverage(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } } internal class SampleAverageCommandString : CommandString { protected override string _CommandDescription => "SampleAverage - SA"; protected override string _CommandString => "SA"; public override byte[] GetParameters() { var ms = new System.IO.MemoryStream(); ms.WriteByte(Convert.ToByte(' ')); return ms.ToArray(); } } /// /// this is a simple class that does a sample average, if it comes back with all railed channel values, it gets another sample average /// (upto a max number of attemps, defined by the constant MAX_TIMES_AROUND) /// this was added as a work around for occasional railed data coming from SA /// 11326 Failed to arm in check trigger navi step /// it may no longer be needed but is added for safety purposes /// public class SampleAverageWithFallback { public List ChannelValues { get; private set; } = new List(); public List DigitalValues { get; private set; } = new List(); private DTS.Common.Interface.DASFactory.ICommunication _sock; private int _moduleIndex; public SampleAverageWithFallback(DTS.Common.Interface.DASFactory.ICommunication sock, int module) { _sock = sock; _moduleIndex = module; } private const int MAX_TIMES_AROUND = 2; public void SyncExecute(int timeAround = 0) { if (MAX_TIMES_AROUND <= timeAround) { return; } var sa1 = new SampleAverage(_sock); sa1.ModuleIndex = _moduleIndex; try { sa1.SyncExecute(); ChannelValues = sa1.ChannelValues; DigitalValues = sa1.DigitalValues; } catch (Exception ex) { APILogger.Log(ex); } bool bGoAgain = false; if (!ChannelValues.Any()) { if (!DigitalValues.Any()) { bGoAgain = true; } } else { bool bFoundNonRailed = false; foreach (var val in ChannelValues) { if (val > short.MinValue && val < short.MaxValue) { bFoundNonRailed = true; break; } } if (!bFoundNonRailed) { bGoAgain = true; } } if (bGoAgain) { SyncExecute(timeAround++); } } } public class SampleAverage : CommandBase { public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } public List ChannelValues { get; } = new List(); public List DigitalValues { get; private set; } = new List(); private readonly SampleAverageCommandString _cs = new SampleAverageCommandString(); public SampleAverage(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public SampleAverage(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } if (null != _responseData) { return; } //already processed? - I added this because ProcessData was getting called by ResponseToString which was populating things multiple times var s = Encoding.ASCII.GetString(response.ToBytes()); var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf("SA"); var end = s.LastIndexOf("\r\n"); if (start < 0 || end < start) { return; } Debug.Assert(start >= 0 && end > start); Debug.Assert(command != null, "command != null"); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength); var data = ResponseData.Split(' '); foreach (var sData in data) { if (double.TryParse(sData, out double d)) { ChannelValues.Add(d); } else { if (!short.TryParse(sData, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out short temp)) continue; var bytes = BitConverter.GetBytes(temp); var boolArray = new bool[bytes.Length * 8]; for (var byteIndex = 0; byteIndex < bytes.Length; byteIndex++) { var b = bytes[byteIndex]; for (var bitIndex = 0; bitIndex < 8; bitIndex++) { boolArray[byteIndex * 8 + bitIndex] = (b & 1 << bitIndex) == 1 << bitIndex; } } DigitalValues = new List(boolArray); } } } } internal class CalDACCommandString : CommandString { internal string GetCalDACValueString(double dGain, double dMaxCurrent) { const double maxCalDACADC = 65535D; const int calDACMidPoint = 32767; var calDACValue = (int)Math.Floor(0.5 + calDACMidPoint + dMaxCurrent / 1 * 1000.0 / (5000.0 / maxCalDACADC)); return $"{calDACValue}"; } public char Channel { get; set; } = '0'; public char EOrX { get; set; } = 'E'; public double Current { get; set; } public double BridgeValue { get; set; } public double Gain { get; set; } protected override string _CommandDescription => "Cal DAC - C"; protected override string _CommandString => "C"; public override byte[] GetParameters() { var ms = new System.IO.MemoryStream(); ms.WriteByte(Convert.ToByte(' ')); ms.WriteByte(Convert.ToByte(Channel)); ms.WriteByte(Convert.ToByte(' ')); ms.WriteByte(Convert.ToByte(EOrX)); ms.WriteByte(Convert.ToByte(' ')); var s = "0"; if (EOrX == 'E') { s = GetCalDACValueString(Gain, Current); } foreach (var c in s) { ms.WriteByte(Convert.ToByte(c)); } return ms.ToArray(); } } public class CalDAC : CommandBase { private CalDACCommandString _commandString { get { var command = baseCommand as TDASCommandPacketBase; return command?.GetCommandStringObject(0) as CalDACCommandString; } } public double BridgeValue { get => _commandString.BridgeValue; set => _commandString.BridgeValue = value; } public double Current { get => _commandString.Current; set => _commandString.Current = value; } public double Gain { get => _commandString.Gain; set => _commandString.Gain = value; } public char EOrX { get => _commandString.EOrX; set => _commandString.EOrX = value; } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } public int Channel { get => int.Parse(new string(_commandString.Channel, 1)); set { if (value < 0 || value > 8) { throw new Exception("channel must be between 1 and 8"); } _commandString.Channel = value.ToString()[0]; } } private readonly CalDACCommandString _cs = new CalDACCommandString(); public CalDAC(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; } public CalDAC(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; } } internal class SetupClearCommandString : CommandString { protected override string _CommandDescription => "Setup Clear - SETUP CLEAR"; protected override string _CommandString => "SETUP CLEAR"; public SetupClearCommandString() { RackCommand = false; } } public class SetupClear : CommandBase { public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } public SetupClear(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new SetupClearCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public SetupClear(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new SetupClearCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; command.RackSerialNumber = base.RackSerialNumber; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf("SETUP: CLEAR"); var end = s.LastIndexOf("\r\n"); Debug.Assert(start >= 0 && end > start); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength); } } internal class SetupClearBroadcastCommandString : CommandString { private int _moduleIndex = 0; public int ModuleIndex { get { return _moduleIndex; } set { _moduleIndex = value; } } protected override string _CommandDescription { get { return "Setup Clear - SETUP CLEAR (*)"; } } protected override string _CommandString { get { if (ModuleIndex >= 0) { return string.Format("*{0}SETUP CLEAR", ModuleIndex); } else { return "*SETUP CLEAR"; } } } public SetupClearBroadcastCommandString(int moduleIndex) { RackCommand = false; _moduleIndex = moduleIndex; } } public class SetupClearBroadcast : CommandBase { public SetupClearBroadcast(DTS.Common.Interface.DASFactory.ICommunication sock, int moduleIndex) : base(sock) { TDASCommandPacketBase command = new TDASCommandPacketBase(new SetupClearBroadcastCommandString(moduleIndex)); baseCommand = command; command.ExpectsData = true; command.RebuildBytes = true; command.RackCommand = false; command.SingleModuleCommand = base.SingleModuleCommand; } public SetupClearBroadcast(DTS.Common.Interface.DASFactory.ICommunication sock, int moduleIndex, int msTimeout) : base(sock, msTimeout) { TDASCommandPacketBase command = new TDASCommandPacketBase(new SetupClearBroadcastCommandString(moduleIndex)); baseCommand = command; command.ExpectsData = true; command.RebuildBytes = true; command.RackCommand = false; command.SingleModuleCommand = base.SingleModuleCommand; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf("SETUP: CLEAR"); var end = s.LastIndexOf("\r\n"); Debug.Assert(start >= 0 && end > start); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength); } } public class TestPrepareCommandString : CommandString { public bool On { get; set; } = true; protected override string _CommandDescription => "TestPrepare "; protected override string _CommandString => "TEST PREPARE"; public override byte[] GetParameters() { return Encoding.ASCII.GetBytes(On ? " ON" : " OFF"); } } public class TestPrepare : CommandBase { private TestPrepareCommandString _CommandString { get { var command = baseCommand as TDASCommandPacketBase; return command?.GetCommandStringObject(0) as TestPrepareCommandString; } } public bool On { get => _CommandString.On; set => _CommandString.On = value; } public int ModuleIndex { get => (baseCommand as TDASCommandPacketBase).ModuleIndex; set => (baseCommand as TDASCommandPacketBase).ModuleIndex = value; } public TestPrepare(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new TestPrepareCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public TestPrepare(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestPrepareCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf("TEST: PREPARE"); var end = s.LastIndexOf("\r\n"); Debug.Assert(start >= 0 && end > start); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength); } } public class QueryTestPrepareCommandString : CommandString { protected override string _CommandDescription => "TEST PREPARE STATUS"; protected override string _CommandString => "TEST PREPARE STATUS"; } public class QueryTestPrepare : CommandBase { private bool _bOn; public bool On { get { if (_responseData == null) { ProcessData(); } return _bOn; } } public int ModuleIndex { get => (baseCommand as TDASCommandPacketBase).ModuleIndex; set => (baseCommand as TDASCommandPacketBase).ModuleIndex = value; } public QueryTestPrepare(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new QueryTestPrepareCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public QueryTestPrepare(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new QueryTestPrepareCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } private const string EXPECTED_RESPONSE = "TEST: PREPARE STATUS? "; private const string DIM_RESPONSE = "TEST: PREPARE STATUS "; protected override void ProcessData() { //TEST: PREPARE STATUS? N var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var start = s.IndexOf(EXPECTED_RESPONSE); var start2 = s.IndexOf(DIM_RESPONSE); var end = s.LastIndexOf("\r\n"); Debug.Assert((start >= 0 || start2 >= 0) && end > start); if (start >= 0) { _responseData = s.Substring(start + EXPECTED_RESPONSE.Length, end - start - EXPECTED_RESPONSE.Length); } else if (start2 >= 0) { _responseData = s.Substring(start2 + DIM_RESPONSE.Length, end - start2 - DIM_RESPONSE.Length); } _bOn = _responseData.Trim().ToUpper().StartsWith("Y"); } } public class TestPrepareBroadcastCommandString : CommandString { private bool _bOn = true; public bool On { get { return _bOn; } set { _bOn = value; } } private int _moduleIndex = 0; public int ModuleIndex { get { return _moduleIndex; } set { _moduleIndex = value; } } protected override string _CommandDescription { get { return "TestPrepare (*)"; } } protected override string _CommandString { get { if (ModuleIndex >= 0) { return string.Format("*{0}TEST PREPARE", ModuleIndex); } else { return "*TEST PREPARE"; } } } public override byte[] GetParameters() { if (On) { return ASCIIEncoding.ASCII.GetBytes(" ON"); } else { return ASCIIEncoding.ASCII.GetBytes(" OFF"); } } public TestPrepareBroadcastCommandString(int moduleIndex) { RackCommand = false; _moduleIndex = moduleIndex; } } public class TestPrepareBroadcast : CommandBase { private TestPrepareBroadcastCommandString _CommandString { get { TDASCommandPacketBase command = baseCommand as TDASCommandPacketBase; return command.GetCommandStringObject(0) as TestPrepareBroadcastCommandString; } } public bool On { get { return _CommandString.On; } set { _CommandString.On = value; } } public TestPrepareBroadcast(DTS.Common.Interface.DASFactory.ICommunication sock, int moduleIndex) : base(sock) { TDASCommandPacketBase command = new TDASCommandPacketBase(new TestPrepareBroadcastCommandString(moduleIndex)); baseCommand = command; //18128 TDAS TEST broadcast command should wait for a response //per TJK we should wait for response here command.ExpectsData = true; command.RebuildBytes = true; command.RackCommand = false; command.SingleModuleCommand = base.SingleModuleCommand; } public TestPrepareBroadcast(DTS.Common.Interface.DASFactory.ICommunication sock, int moduleIndex, int msTimeout) : base(sock, msTimeout) { TDASCommandPacketBase command = new TDASCommandPacketBase(new TestPrepareBroadcastCommandString(moduleIndex)); baseCommand = command; //18128 TDAS TEST broadcast command should wait for a response //per TJK we should wait for response here command.ExpectsData = true; command.RebuildBytes = true; command.RackCommand = false; command.SingleModuleCommand = base.SingleModuleCommand; } } public class TestChannelRunBroadcastCommandString : CommandString { //18127 Test Channel Run Broadcast can complete before response is received and processed //reply with TOO SHORT unless we see CHANNEL RUN in response ... private string _requiredResponseString = "CHANNEL RUN"; public override string RequiredResponseString { get => _requiredResponseString; set => _requiredResponseString = value; } public enum TestType { Pre, Post } public TestType Type { get; set; } = TestType.Pre; protected override string _CommandDescription => "Test Channel Run (*) "; public int ModuleIndex { get; set; } protected override string _CommandString => ModuleIndex >= 0 ? $"*{ModuleIndex}TEST CHANNEL RUN" : "*TEST CHANNEL RUN"; public override byte[] GetParameters() { const string channel = "ALL"; switch (Type) { case TestType.Pre: return Encoding.ASCII.GetBytes($" PRE {channel}"); case TestType.Post: return Encoding.ASCII.GetBytes($" POST {channel}"); default: throw new NotSupportedException("Unknown Test type " + Type); } } public TestChannelRunBroadcastCommandString(int moduleIndex) { ModuleIndex = moduleIndex; } } public class TestChannelRunBroadcast : CommandBase { public TestChannelRunBroadcast(DTS.Common.Interface.DASFactory.ICommunication sock, int moduleIndex) : base(sock) { var command = new TDASCommandPacketBase(new TestChannelRunBroadcastCommandString(moduleIndex)); baseCommand = command; command.ExpectsData = true; command.RebuildBytes = true; command.RackCommand = false; command.SingleModuleCommand = base.SingleModuleCommand; } public TestChannelRunBroadcast(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout, int moduleIndex) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestChannelRunBroadcastCommandString(moduleIndex)); baseCommand = command; command.ExpectsData = true; command.RebuildBytes = true; command.RackCommand = false; command.SingleModuleCommand = base.SingleModuleCommand; } } public class TestChannelRunCommandString : CommandString { private int _channelIndex; public int ChannelIndex { get => _channelIndex; set => _channelIndex = value; } public enum TestType { Pre, Post } public TestType Type { get; set; } = TestType.Pre; protected override string _CommandDescription => "Test Channel Run "; protected override string _CommandString => "TEST CHANNEL RUN"; public override byte[] GetParameters() { string channel = ChannelIndex >= 0 ? ChannelIndex.ToString() : "ALL"; switch (Type) { case TestType.Pre: return Encoding.ASCII.GetBytes($" PRE {channel}"); case TestType.Post: return Encoding.ASCII.GetBytes($" POST {channel}"); default: throw new NotSupportedException("Unknown Test type " + Type); } } } public class TestChannelRun : CommandBase { private TestChannelRunCommandString _commandString { get { var command = baseCommand as TDASCommandPacketBase; return command?.GetCommandStringObject(0) as TestChannelRunCommandString; } } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } public bool RackCommand { get => ((TDASCommandPacketBase)baseCommand).RackCommand; set { ((TDASCommandPacketBase)baseCommand).RackCommand = value; _commandString.RackCommand = true; } } public int ChannelIndex { get => _commandString.ChannelIndex; set => _commandString.ChannelIndex = value; } public TestChannelRun(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new TestChannelRunCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public TestChannelRun(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestChannelRunCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } string s = Encoding.ASCII.GetString(response.ToBytes()); var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf("TEST: CHANNEL RUN"); var end = s.LastIndexOf("\r\n"); Debug.Assert(start >= 0 && end > start); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength); if (IsErrored()) { throw new CommandException(CommandErrorReason.InvalidMode, ResponseData); } } } public class TestChannelReadCommandString : CommandString { public int ChannelIndex { get; set; } public enum TestType { Pre, Post } public TestType Type { get; set; } = TestType.Pre; protected override string _CommandDescription => "Test Channel Read "; protected override string _CommandString => "TEST CHANNEL READ"; public override byte[] GetParameters() { var channel = ChannelIndex >= 0 ? ChannelIndex.ToString() : "ALL"; switch (Type) { case TestType.Pre: return Encoding.ASCII.GetBytes($" PRE {channel}"); case TestType.Post: return Encoding.ASCII.GetBytes($" POST {channel}"); default: throw new NotSupportedException("Unknown Test type " + Type); } } public TestChannelReadCommandString() { } public TestChannelReadCommandString(TestType type) { Type = type; } } public class TestSquibChannelRead : CommandBase { private TestChannelReadCommandString _commandString { get { var command = baseCommand as TDASCommandPacketBase; return command?.GetCommandStringObject(0) as TestChannelReadCommandString; } } public int ChannelIndex { get => _commandString.ChannelIndex; set => _commandString.ChannelIndex = value; } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } private double _currentStdDevADC = double.NaN; public double CurrentStdDevADC { get { if (double.IsNaN(_currentStdDevADC)) { ProcessData(); } return _currentStdDevADC; } } private double _currentPreZero = double.NaN; public double CurrentPreZero { get { if (double.IsNaN(_currentPreZero)) { ProcessData(); } return _currentPreZero; } } private double _currentScaleFactorMv = double.NaN; public double CurrentScaleFactorMv { get { if (double.IsNaN(_currentScaleFactorMv)) { ProcessData(); } return _currentScaleFactorMv; } } private double _voltageStdDevADC = double.NaN; public double VoltageStdDevADC { get { if (double.IsNaN(_voltageStdDevADC)) { ProcessData(); } return _voltageStdDevADC; } } private double _voltagePreZero = double.NaN; public double VoltagePreZero { get { if (double.IsNaN(_voltagePreZero)) { ProcessData(); } return _voltagePreZero; } } private double _voltageScaleFactorMv = double.NaN; public double VoltageScaleFactorMv { get { if (double.IsNaN(_voltageScaleFactorMv)) { ProcessData(); } return _voltageScaleFactorMv; } } private double _measuredOhms = double.NaN; public double MeasuredOhms { get { if (double.IsNaN(_measuredOhms)) { ProcessData(); } return _measuredOhms; } } public TestSquibChannelRead(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new TestChannelReadCommandString()); baseCommand = command; command.RebuildBytes = true; } public TestSquibChannelRead(DTS.Common.Interface.DASFactory.ICommunication sock, TestChannelReadCommandString.TestType type) : base(sock) { var command = new TDASCommandPacketBase(new TestChannelReadCommandString(type)); baseCommand = command; command.RebuildBytes = true; } public TestSquibChannelRead(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestChannelReadCommandString()); baseCommand = command; command.RebuildBytes = true; } private enum ResponseFields { option = 0, channel, measuredOhms, voltageScaleFactorMv, voltagePreZero, voltageStdDevInADC, currentScaleFactorMv, currentPreZero, currentStdDevInADC } public bool CheckData() { ProcessData(); return true; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf("TEST: CHANNEL READ"); var end = s.LastIndexOf("\r\n"); Debug.Assert(start >= 0 && end > start); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength); var data = ResponseData.Split(' '); for (var i = 0; i < data.Length; i++) { var field = (ResponseFields)i; switch (field) { case ResponseFields.option: break; case ResponseFields.channel: break; case ResponseFields.currentPreZero: _currentPreZero = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.currentScaleFactorMv: _currentScaleFactorMv = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.currentStdDevInADC: _currentStdDevADC = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.measuredOhms: _measuredOhms = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.voltagePreZero: _voltagePreZero = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.voltageScaleFactorMv: _voltageScaleFactorMv = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.voltageStdDevInADC: _voltageStdDevADC = TDASNumberHelper.ParseDouble(data[i]); break; } } } } public sealed class TDASNumberHelper { public static double ParseDouble(string s) { if (s.EndsWith("N")) { s = s.Substring(0, s.Length - 1); } else if (s.EndsWith("P")) { s = s.Substring(0, s.Length - 1); } if (double.TryParse(s, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out double d)) { return d; } if (s.ToLower() == "inf") { return double.PositiveInfinity; } throw new InvalidCastException("not a double: " + s); } public static int ParseInt(string s) { if (s.EndsWith("N")) { s = s.Substring(0, s.Length - 1); } else if (s.EndsWith("P")) { } if (int.TryParse(s, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out int d)) { return d; } if (s.ToLower() == "inf") { return int.MaxValue; } throw new InvalidCastException("not a int: " + s); } } public class TestChannelRead : CommandBase { private TestChannelReadCommandString _commandString { get { var command = baseCommand as TDASCommandPacketBase; return command?.GetCommandStringObject(0) as TestChannelReadCommandString; } } public int ChannelIndex { get => _commandString.ChannelIndex; set => _commandString.ChannelIndex = value; } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } public double Gain { get; set; } public double MvScaleFactorADC { get; set; } public int ZeroMvADC { get; set; } public double SensorOffsetMv { get; set; } public double StdDevGain1ADC { get; set; } /// /// 14233 Negative Excitation Reported by TDAS hardware not showing in Diagnostics /// indicates that excitation when measured was negative /// public bool NegativeExcitation { get; private set; } private double _excitation; public double Excitation { get => _excitation; set => _excitation = Math.Abs(value); } public int ZeroAverageADCValue { get; set; } public double ZeroStdDevAtGainADC { get; set; } public int VoltageInsertionDeltaADC { get; set; } public int ShuntCalibrationDeltaADC { get; set; } public TestChannelRead(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new TestChannelReadCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public TestChannelRead(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestChannelReadCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public TestChannelRead(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout, TestChannelReadCommandString.TestType type) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestChannelReadCommandString(type)); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } private enum ResponseFields { option = 0, channel, gain, mvADCScaleFactor, zeroMvInADC, offsetInMV, stdDevInADC, excitation, zeroAverageValueADC, zeroStdDevADC, voltageInsertionDelta, shuntCalibrationDelta } public bool CheckData() { ProcessData(); return true; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf("TEST: CHANNEL READ"); var end = s.LastIndexOf("\r\n"); Debug.Assert(start >= 0 && end > start); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength); var data = ResponseData.Split(' '); for (var i = 0; i < data.Length; i++) { var field = (ResponseFields)i; switch (field) { case ResponseFields.channel: break; case ResponseFields.excitation: { string temp = data[i]; Excitation = TDASNumberHelper.ParseDouble(temp); //not sure how or why, but historical records indicate excitation can come back //in the form of 1234N where N is to indicate a negative value NegativeExcitation = Excitation < 0 || temp.EndsWith("N"); Excitation = (Math.Abs(Excitation)); } break; case ResponseFields.gain: Gain = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.mvADCScaleFactor: MvScaleFactorADC = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.offsetInMV: SensorOffsetMv = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.option: break; case ResponseFields.shuntCalibrationDelta: ShuntCalibrationDeltaADC = TDASNumberHelper.ParseInt(data[i]); break; case ResponseFields.stdDevInADC: StdDevGain1ADC = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.voltageInsertionDelta: VoltageInsertionDeltaADC = TDASNumberHelper.ParseInt(data[i]); break; case ResponseFields.zeroAverageValueADC: ZeroAverageADCValue = TDASNumberHelper.ParseInt(data[i]); break; case ResponseFields.zeroMvInADC: ZeroMvADC = TDASNumberHelper.ParseInt(data[i]); break; case ResponseFields.zeroStdDevADC: ZeroStdDevAtGainADC = TDASNumberHelper.ParseDouble(data[i]); break; } } } } public class TestChannelReadAll : CommandBase { public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } private readonly Dictionary _gains = new Dictionary(); public double GetGain(int channel) { return _gains.ContainsKey(channel) ? _gains[channel] : double.NaN; } private readonly Dictionary _scaleFactorADCs = new Dictionary(); public double GetmVScaleFactorADC(int channel) { return _scaleFactorADCs.ContainsKey(channel) ? _scaleFactorADCs[channel] : double.NaN; } private readonly Dictionary _zeroMvADCs = new Dictionary(); public double GetZeromVADC(int channel) { return _zeroMvADCs.ContainsKey(channel) ? _zeroMvADCs[channel] : double.NaN; } private readonly Dictionary _sensorOffsetmVs = new Dictionary(); public double GetSensorOffsetmV(int channel) { return _sensorOffsetmVs.ContainsKey(channel) ? _sensorOffsetmVs[channel] : double.NaN; } private readonly Dictionary _stdDevGain1ADCs = new Dictionary(); public double GetStdDevGain1ADC(int channel) { return _stdDevGain1ADCs.ContainsKey(channel) ? _stdDevGain1ADCs[channel] : double.NaN; } private readonly Dictionary _excitations = new Dictionary(); public double GetExcitation(int channel) { return _excitations.ContainsKey(channel) ? _excitations[channel] : double.NaN; } /// /// indicates that the excitation when measured was negative /// 14233 Negative Excitation Reported by TDAS hardware not showing in Diagnostics /// key is channel /// private readonly Dictionary _negativeExcitation = new Dictionary(); /// /// returns whether excitation when measured was negative or not /// 14233 Negative Excitation Reported by TDAS hardware not showing in Diagnostics /// default is false (in the case channel was not measured) /// /// /// public bool GetNegativeExcitation(int channel) { return _negativeExcitation.ContainsKey(channel) ? _negativeExcitation[channel] : false; } private readonly Dictionary _zeroAverageADCValues = new Dictionary(); public int GetZeroAverageADCValue(int channel) { return _zeroAverageADCValues.ContainsKey(channel) ? _zeroAverageADCValues[channel] : 0; } private readonly Dictionary _zeroStdDevAtGainADCs = new Dictionary(); public double GetZeroStdDevAtGainADC(int channel) { return _zeroStdDevAtGainADCs.ContainsKey(channel) ? _zeroStdDevAtGainADCs[channel] : double.NaN; } private readonly Dictionary _voltageInsertionDeltaADCs = new Dictionary(); public int GetVoltagteInsertionDeltaADC(int channel) { return _voltageInsertionDeltaADCs.ContainsKey(channel) ? _voltageInsertionDeltaADCs[channel] : 0; } private readonly Dictionary _shuntCalibrationDeltaADCs = new Dictionary(); public int GetShuntCalibrationDeltaADC(int channel) { return _shuntCalibrationDeltaADCs.ContainsKey(channel) ? _shuntCalibrationDeltaADCs[channel] : 0; } public TestChannelReadAll(DTS.Common.Interface.DASFactory.ICommunication sock, int linesExpected) : base(sock) { var command = new TDASCommandPacketBase(new TestChannelReadCommandString()); command.ExpectsMultipleLines = true; command.LinesExpected = linesExpected; command.SingleModuleCommand = base.SingleModuleCommand; baseCommand = command; var tcr = (TestChannelReadCommandString)command.GetCommandStringObject(0); tcr.ChannelIndex = -1; command.RebuildBytes = true; } public TestChannelReadAll(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout, int linesExpected) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestChannelReadCommandString()); command.ExpectsMultipleLines = true; command.LinesExpected = linesExpected; command.SingleModuleCommand = base.SingleModuleCommand; baseCommand = command; var tcr = (TestChannelReadCommandString)command.GetCommandStringObject(0); tcr.ChannelIndex = -1; command.RebuildBytes = true; } public TestChannelReadAll(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout, TestChannelReadCommandString.TestType type) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestChannelReadCommandString(type)); command.SingleModuleCommand = base.SingleModuleCommand; baseCommand = command; command.RebuildBytes = true; } private enum ResponseFields { option = 0, channel, gain, mvADCScaleFactor, zeroMvInADC, offsetInMV, stdDevInADC, excitation, zeroAverageValueADC, zeroStdDevADC, voltageInsertionDelta, shuntCalibrationDelta } public bool CheckData() { ProcessData(); return true; } protected override void ProcessData() { if (!(baseResponse is TDASCommandPacketBase response)) { APILogger.Log("TestChannelReadAll - return early, baseResponse null"); return; } var s = Encoding.ASCII.GetString(response.ToBytes()); APILogger.Log($"TestChannelReadAll - response: {s}"); var lines = s.Split(new[] { "\r\n" }, StringSplitOptions.None); _responseData = s; foreach (var line in lines) { var indexOfChecksum = line.IndexOf('~'); var sTemp = line; if (indexOfChecksum > 0) { sTemp = line.Substring(0, indexOfChecksum); APILogger.Log($"TestChannelReadAll - cut line down from {line} to {sTemp}"); } var start = sTemp.IndexOf("TEST: CHANNEL READ"); if (start < 0) { APILogger.Log($"TestChannelReadAll - continuing - missed Test: CHANNEL READ"); continue; } sTemp = sTemp.Substring(start + 19); sTemp = sTemp.Trim(); APILogger.Log($"TestChannelReadAll - processing: {sTemp}"); var data = sTemp.Split(' '); var channel = 0; for (var i = 0; i < data.Length; i++) { var field = (ResponseFields)i; switch (field) { case ResponseFields.channel: channel = int.Parse(data[i]); break; case ResponseFields.excitation: { var temp = data[i]; //what's going on here? var d = TDASNumberHelper.ParseDouble(temp); //I'm not sure what or how, but historical records indicate that //we can get a value in the form of 1234N where the N indicates negative number _negativeExcitation[channel] = d < 0 || temp.EndsWith("N"); d = Math.Abs(d); _excitations[channel] = d; } break; case ResponseFields.gain: _gains[channel] = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.mvADCScaleFactor: _scaleFactorADCs[channel] = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.offsetInMV: _sensorOffsetmVs[channel] = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.option: break; case ResponseFields.shuntCalibrationDelta: _shuntCalibrationDeltaADCs[channel] = TDASNumberHelper.ParseInt(data[i]); break; case ResponseFields.stdDevInADC: _stdDevGain1ADCs[channel] = TDASNumberHelper.ParseDouble(data[i]); break; case ResponseFields.voltageInsertionDelta: _voltageInsertionDeltaADCs[channel] = TDASNumberHelper.ParseInt(data[i]); break; case ResponseFields.zeroAverageValueADC: _zeroAverageADCValues[channel] = TDASNumberHelper.ParseInt(data[i]); break; case ResponseFields.zeroMvInADC: _zeroMvADCs[channel] = TDASNumberHelper.ParseInt(data[i]); break; case ResponseFields.zeroStdDevADC: _zeroStdDevAtGainADCs[channel] = TDASNumberHelper.ParseDouble(data[i]); break; } } } } } internal class SetupDIMChannelLoadCommandString : CommandString { public int Channel { get; set; } = 1; public string InputMode { get; set; } = "CCNO"; public string UserChannelNumber { get; set; } = "DI"; public string UserChannelLocation { get; set; } = "DI"; public bool Invert { get; set; } protected override string _CommandDescription => "SetupChannelLoad (DIM)- SCL"; protected override string _CommandString => "SCL"; public override byte[] GetParameters() { var s = $" {Channel} {InputMode} {(Invert ? "T" : "F")} \"{UserChannelNumber}\" \"{UserChannelLocation}\""; return Encoding.ASCII.GetBytes(s); } public SetupDIMChannelLoadCommandString() { RackCommand = false; } } public class SetupDIMChannel : CommandBase { private SetupDIMChannelLoadCommandString _commandString { get { var basePacket = baseCommand as TDASCommandPacketBase; return basePacket?.GetCommandStringObject(0) as SetupDIMChannelLoadCommandString; } } public int ChannelNumber { set => _commandString.Channel = value; } public enum InputModes { CCNO = 0x01, CCNC = 0x02, VMLH = 0x03, VMHL = 0x04 } public InputModes InputMode { set => _commandString.InputMode = value.ToString(); } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } public SetupDIMChannel(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new SetupDIMChannelLoadCommandString()); baseCommand = command; command.RebuildBytes = true; } public SetupDIMChannel(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new SetupDIMChannelLoadCommandString()); baseCommand = command; command.RebuildBytes = true; } protected override void ProcessData() { base.ProcessData(); if (null == _responseData || IsErrored()) { throw new Exception("SetupDIMChannel failed (DIM)- " + ResponseData); } } } internal class SetupSquibLoadCommandString : CommandString { public int Channel { get; set; } = 1; public char FireMode { get; set; } = 'F'; public char MeasurementMode { get; set; } = 'F'; public char CurrentFilterOption { get; set; } = 'F'; public char VoltageFilterOption { get; set; } = 'F'; public double DelayMS { get; set; } public double DurationMS { get; set; } public double SquibResistanceMin { get; set; } public double SquibResistanceMax { get; set; } public double OutputCurrent { get; set; } = 2D; public string UserChannelNumber { get; set; } = "SQ"; public string UserChannelLocation { get; set; } = "SQ"; protected override string _CommandDescription => "SetupChannelLoad (SQUIB)- SCL"; protected override string _CommandString => "SCL"; public override byte[] GetParameters() { var s = $" S{Channel} {FireMode}{MeasurementMode}{CurrentFilterOption}{VoltageFilterOption} {DelayMS:g} {DurationMS:g} {SquibResistanceMin:g} {SquibResistanceMax:g} {OutputCurrent:g} {UserChannelNumber} {UserChannelLocation}"; return Encoding.ASCII.GetBytes(s); } public SetupSquibLoadCommandString() { RackCommand = false; } } public class SetupSquibLoad : CommandBase { private SetupSquibLoadCommandString _commandString { get { var basePacket = baseCommand as TDASCommandPacketBase; return basePacket?.GetCommandStringObject(0) as SetupSquibLoadCommandString; } } public int ChannelNumber { set => _commandString.Channel = value; } public string UserChannelNumber { set { if (value.Length > 4) { throw new Exception("Channel number must be 4 characters or less"); } if (value.Contains(' ') && !value.Contains('\"')) { throw new Exception("spaces must be within quotes"); } _commandString.UserChannelNumber = value; } } public enum FireModes { CapacitorDischarge, ConstantCurrent, AlternatingCurrent }; public FireModes FireMode { set { switch (value) { case FireModes.AlternatingCurrent: _commandString.FireMode = 'A'; break; case FireModes.CapacitorDischarge: _commandString.FireMode = 'D'; break; case FireModes.ConstantCurrent: _commandString.FireMode = 'C'; break; default: throw new NotSupportedException("Unknown FireMode" + value); } } } public enum MeasurementTypes { Insertion, Voltage }; public MeasurementTypes MeasurementType { set { switch (value) { case MeasurementTypes.Insertion: _commandString.MeasurementMode = 'I'; break; case MeasurementTypes.Voltage: _commandString.MeasurementMode = 'V'; break; default: throw new NotSupportedException("Unknown measurementtype " + value); } } } /// /// should be set to True if samplerate > 20k /// fixed filter, 4k is max hardware filtering rate /// public bool BypassCurrentFilter { set => _commandString.CurrentFilterOption = value ? 'B' : 'F'; } /// /// should be set to True if samplerate is > 20k /// see explanation above /// public bool BypassVoltageFilter { set => _commandString.VoltageFilterOption = value ? 'B' : 'F'; } public double DelayMS { get => _commandString.DelayMS; set => _commandString.DelayMS = value; } public double DurationMS { get => _commandString.DurationMS; set => _commandString.DurationMS = value; } public string Location { set { if (value.Length > 16) { throw new Exception("Location must be less than 16 characters"); } if (value.Contains(' ') && !value.Contains('\"')) { throw new Exception("spaces must be within quotes"); } _commandString.UserChannelLocation = value; } } public double SquibResistanceMin { get => _commandString.SquibResistanceMin; set => _commandString.SquibResistanceMin = value; } public double SquibResistanceMax { get { return _commandString.SquibResistanceMax; } set { _commandString.SquibResistanceMax = value; } } public double OutputCurrent { get => _commandString.OutputCurrent; set => _commandString.OutputCurrent = value; } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } public SetupSquibLoad(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new SetupSquibLoadCommandString()); baseCommand = command; command.RebuildBytes = true; } public SetupSquibLoad(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new SetupSquibLoadCommandString()); baseCommand = command; command.RebuildBytes = true; } protected override void ProcessData() { base.ProcessData(); if (null == _responseData || IsErrored()) { throw new Exception("SetupChannelLoad failed (squib)- " + ResponseData); } } } public class TestSquibCommandString : CommandString { public int ChannelIndex { get; set; } protected override string _CommandDescription => "Test Squib "; protected override string _CommandString => "TS"; public override byte[] GetParameters() { var s = $" {ChannelIndex}"; return Encoding.ASCII.GetBytes(s); } } public class TestSquib : CommandBase { private TestSquibCommandString _commandString { get { var command = baseCommand as TDASCommandPacketBase; return command?.GetCommandStringObject(0) as TestSquibCommandString; } } public int ChannelIndex { get => _commandString.ChannelIndex; set => _commandString.ChannelIndex = value / 2; } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } private double _resistanceOhms = double.NaN; public double ResistanceOhms { get { if (double.IsNaN(_resistanceOhms)) { ProcessData(); } return _resistanceOhms; } set => _resistanceOhms = value; } public TestSquib(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { TDASCommandPacketBase command = new TDASCommandPacketBase(new TestSquibCommandString()); baseCommand = command; command.RebuildBytes = true; } public TestSquib(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestSquibCommandString()); baseCommand = command; command.RebuildBytes = true; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf(":"); var end = s.LastIndexOf("\r\n"); Debug.Assert(start >= 0 && end > start); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength).Trim(); if (double.TryParse(ResponseData, out double d)) { _resistanceOhms = d; } } } class TestSquibArrayCommandString : CommandString { protected override string _CommandDescription => "TSA"; protected override string _CommandString => "TSA"; } public class TestSquibArray : CommandBase { public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } private double[] _resistanceOhms; public double[] ResistanceOhms { get { if (null == _resistanceOhms) { ProcessData(); } return _resistanceOhms; } set => _resistanceOhms = value; } public TestSquibArray(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new TestSquibArrayCommandString()); baseCommand = command; command.RebuildBytes = true; } public TestSquibArray(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestSquibArrayCommandString()); baseCommand = command; command.RebuildBytes = true; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf(":"); var end = s.LastIndexOf("\r\n"); Debug.Assert(start >= 0 && end > start); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength).Trim(); var tokens = ResponseData.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); _resistanceOhms = new double[tokens.Length]; for (var i = 0; i < tokens.Length; i++) { if (double.TryParse(tokens[i], out double d)) { _resistanceOhms[i] = d; } else { _resistanceOhms[i] = double.NaN; } } } } public class TestSquibVoltageCommandString : CommandString { protected override string _CommandDescription => "Test Squib Voltage"; protected override string _CommandString => "TSV"; } public class TestSquibVoltage : CommandBase { public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } private double _squibVoltage = double.NaN; public double SquibVoltage { get { if (double.IsNaN(_squibVoltage)) { ProcessData(); } return _squibVoltage; } set => _squibVoltage = value; } public TestSquibVoltage(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new TestSquibVoltageCommandString()); baseCommand = command; command.RebuildBytes = true; } public TestSquibVoltage(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new TestSquibVoltageCommandString()); baseCommand = command; command.RebuildBytes = true; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var start = s.IndexOf(":"); var end = s.LastIndexOf("\r\n"); Debug.Assert(start >= 0 && end > start); var offset = 2; //Data is 2 past the ":" ("...0TSV: nn.nnnn\r\n") _responseData = s.Substring(start + offset, end - start - offset).Trim(); if (double.TryParse(ResponseData, out double d)) { SquibVoltage = d; } } } internal class SetupDigitalLoadCommandString : CommandString { public int Channel { get; set; } = 1; public string Mode { get; set; } public double DelayMS { get; set; } public double DurationMS { get; set; } protected override string _CommandDescription => "SetupChannelLoad (digital)- SCL"; protected override string _CommandString => "SCL"; public override byte[] GetParameters() { var s = $" D{Channel} {Mode} {DelayMS} {DurationMS}"; return Encoding.ASCII.GetBytes(s); } public SetupDigitalLoadCommandString() { RackCommand = false; } } public class SetupDigitalLoad : CommandBase { private SetupDigitalLoadCommandString _commandString { get { var basePacket = baseCommand as TDASCommandPacketBase; return basePacket?.GetCommandStringObject(0) as SetupDigitalLoadCommandString; } } public int ChannelNumber { set => _commandString.Channel = value; } public enum OutputModes { VHL, CCNO, CCNC, VLH }; public OutputModes OutputMode { set { var mode = "5VLH"; switch (value) { case OutputModes.CCNC: case OutputModes.CCNO: mode = value.ToString(); break; case OutputModes.VHL: mode = "5VHL"; break; case OutputModes.VLH: mode = "5VLH"; break; } _commandString.Mode = mode; } } public double DelayMS { get => _commandString.DelayMS; set => _commandString.DelayMS = value; } public double DurationMS { get => _commandString.DurationMS; set => _commandString.DurationMS = value; } public int ModuleIndex { get => ((TDASCommandPacketBase)baseCommand).ModuleIndex; set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; } public SetupDigitalLoad(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new SetupDigitalLoadCommandString()); baseCommand = command; command.RebuildBytes = true; } public SetupDigitalLoad(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new SetupDigitalLoadCommandString()); baseCommand = command; command.RebuildBytes = true; } protected override void ProcessData() { base.ProcessData(); if (IsErrored()) { throw new Exception("SetupChannelLoad failed (digital)- " + ResponseData); } } } public class AUXIDCommandString : CommandString { protected override string _CommandDescription => "Auxilary ID (AUX ID) "; protected override string _CommandString => "AUX ID"; public int ChannelNumber { get; set; } = 33; public override byte[] GetParameters() { var s = $" {ChannelNumber}"; return Encoding.ASCII.GetBytes(s); } } public class AUXID : CommandBase { private AUXIDCommandString _commandString { get { var command = baseCommand as TDASCommandPacketBase; return command?.GetCommandStringObject(0) as AUXIDCommandString; } } public int ChannelNumber { get => _commandString.ChannelNumber; set => _commandString.ChannelNumber = value; } public AUXID(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { var command = new TDASCommandPacketBase(new AUXIDCommandString()); command.RackCommand = false; command.ModuleIndex = 0; baseCommand = command; command.RebuildBytes = true; } public AUXID(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { var command = new TDASCommandPacketBase(new AUXIDCommandString()); baseCommand = command; command.RackCommand = false; command.ModuleIndex = 0; command.RebuildBytes = true; } public string[] Ids { get; private set; } = new string[0]; protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var s = Encoding.ASCII.GetString(response.ToBytes()); var start = s.IndexOf("1000AUX ID:"); var end = s.LastIndexOf("\r\n"); if (start < 0 || end < start) { return; } Debug.Assert(start >= 0 && end > start); const int csLength = 12; //1000AUX ID: _responseData = s.Substring(start + csLength, end - start - csLength); var data = ResponseData.Split(' '); //assume format is, so strip off first and last block and process middle var ids = new List(); for (var i = 1; i < data.Length - 1; i++) { ids.Add(data[i]); } Ids = ids.ToArray(); } } public class G5DockStatCommandString : CommandString { protected override string _CommandDescription => "Dock Stat "; protected override string _CommandString => "DOCK STAT"; } public class G5DockStat : CommandBase { private double _batteryMilliVolts; public double BatteryMilliVolts { get => _batteryMilliVolts; set => _batteryMilliVolts = value; } private bool _batteryCharging; public bool BatteryCharging { get => _batteryCharging; set => _batteryCharging = value; } public enum BatteryChargeStates { red, yellow, green }; private BatteryChargeStates _batteryChargeLevel; public BatteryChargeStates BatteryChargeLevel { get => _batteryChargeLevel; set => _batteryChargeLevel = value; } private bool WarnIfDocNotFound { get; set; } = false; public G5DockStat(DTS.Common.Interface.DASFactory.ICommunication sock, bool bWarnIfDockNotFound) : base(sock) { WarnIfDocNotFound = bWarnIfDockNotFound; var command = new TDASCommandPacketBase(new G5DockStatCommandString()); baseCommand = command; command.RebuildBytes = true; _batteryChargeLevel = BatteryChargeStates.red; } protected G5DockStat(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { WarnIfDocNotFound = false; var command = new TDASCommandPacketBase(new G5DockStatCommandString()); baseCommand = command; command.RebuildBytes = true; _batteryChargeLevel = BatteryChargeStates.red; } private enum ResponseFields { inputVolts = 3, unknown1, unknown2, ledOnTime, ledOffTime, batteryChargeState } public bool CheckData() { ProcessData(); return true; } public bool DockStationPresent { get; set; } protected override void ProcessData() { var response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } var r = new Random(DateTime.Now.Millisecond); var s = Encoding.ASCII.GetString(response.ToBytes()); //if (r.Next(0,100) > 60) //{ // s = "1000ERR: DOCKING STATION not present"; //} var command = baseCommand as TDASCommandPacketBase; var start = s.IndexOf("1000DOCK STAT", StringComparison.Ordinal); var end = s.LastIndexOf("\r\n", StringComparison.Ordinal); if (start < 0 || end < start) //docking station not present { DockStationPresent = false; _batteryMilliVolts = double.NaN; _batteryChargeLevel = BatteryChargeStates.green; _batteryCharging = false; _responseData = s; if (WarnIfDocNotFound) { PageErrorEvent.SurfaceApplicationError(string.Format(Strings.DockingStationNotFound, recorder.SerialNumber)); } return; } else { DockStationPresent = true; } Debug.Assert(start >= 0 && end > start); var csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength); var data = ResponseData.Split(' '); for (var i = 0; i < data.Length; i++) { var field = (ResponseFields)i; switch (field) { case ResponseFields.inputVolts: { _batteryMilliVolts = double.Parse(data[i], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture) * 1000D; } break; case ResponseFields.ledOnTime: _batteryCharging = data[i] == "1000"; break; case ResponseFields.batteryChargeState: switch (data[i]) { case "3": _batteryChargeLevel = BatteryChargeStates.green; break; case "2": _batteryChargeLevel = BatteryChargeStates.yellow; break; default: _batteryChargeLevel = BatteryChargeStates.red; break; } break; } } } } public class TestBatteryCommandString : CommandString { protected override string _CommandDescription { get { return "Test Battery "; } } protected override string _CommandString { get { return "TB"; } } public TestBatteryCommandString() { } } public class TestBattery : CommandBase { private TestBatteryCommandString _commandString { get { TDASCommandPacketBase command = baseCommand as TDASCommandPacketBase; return command.GetCommandStringObject(0) as TestBatteryCommandString; } } public int ModuleIndex { get { return (baseCommand as TDASCommandPacketBase).ModuleIndex; } set { (baseCommand as TDASCommandPacketBase).ModuleIndex = value; } } private double _batteryMilliVolts; public double BatteryMilliVolts { get { return _batteryMilliVolts; } } public TestBattery(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { TDASCommandPacketBase command = new TDASCommandPacketBase(new TestBatteryCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public TestBattery(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { TDASCommandPacketBase command = new TDASCommandPacketBase(new TestBatteryCommandString()); baseCommand = command; command.RebuildBytes = true; command.SingleModuleCommand = base.SingleModuleCommand; } public bool CheckData() { ProcessData(); return true; } protected override void ProcessData() { TDASCommandPacketBase response = baseResponse as TDASCommandPacketBase; if (null == response) { return; } string s = System.Text.ASCIIEncoding.ASCII.GetString(response.ToBytes()); TDASCommandPacketBase command = baseCommand as TDASCommandPacketBase; int start = s.IndexOf("TB:"); int end = s.LastIndexOf("\r\n"); System.Diagnostics.Debug.Assert(start >= 0 && end > start); int csLength = command.GetCommandString(0).Length + 2; _responseData = s.Substring(start + csLength, end - start - csLength); string[] data = ResponseData.Split(' '); if (0 < data.Length) { _batteryMilliVolts = Convert.ToDouble(data[0]) * 1000D; } } } public class SetLEDCommandString : CommandString { protected override string _CommandDescription => "Set LED "; protected override string _CommandString => "L"; public string Light { get; set; } public string State { get; set; } public SetLEDCommandString(string state) { Light = "CAL"; State = state; } public override byte[] GetParameters() { var sb = new StringBuilder(); sb.Append(" "); sb.Append(Light); sb.Append(" "); sb.Append(State); return Encoding.ASCII.GetBytes(sb.ToString()); } } public class SetLED : CommandBase { private SetLEDCommandString _commandString { get { var command = baseCommand as TDASCommandPacketBase; return command?.GetCommandStringObject(0) as SetLEDCommandString; } } private SetLEDCommandString _cs; public SetLED(DTS.Common.Interface.DASFactory.ICommunication sock, string stateString) : base(sock) { _cs = new SetLEDCommandString(stateString); var command = new TDASCommandPacketBase(_cs); baseCommand = command; command.RebuildBytes = true; } public string State { get => _commandString.State; set => _commandString.State = value; } } }