740 lines
30 KiB
C#
740 lines
30 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using DTS.Common.Enums.Communication;
|
|
using DTS.Common.Enums.DASFactory;
|
|
using DTS.Common.ICommunication;
|
|
using DTS.Common.Utilities;
|
|
using DTS.Common.Utilities.Logging;
|
|
|
|
namespace DTS.DASLib.Command.TDAS
|
|
{
|
|
public class AAFilter : CommandBase
|
|
{
|
|
|
|
private TDASCommandPacketBase _command => baseCommand as TDASCommandPacketBase;
|
|
private AAFilterCommandString _aafCommand => _command.GetCommandStringObject(0) as AAFilterCommandString;
|
|
|
|
public int ModuleIndex
|
|
{
|
|
get => _command.ModuleIndex;
|
|
set => _command.ModuleIndex = value;
|
|
}
|
|
|
|
public float Frequency
|
|
{
|
|
get => _aafCommand.Frequency;
|
|
set => _aafCommand.Frequency = value;
|
|
}
|
|
|
|
public AAFilter(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock)
|
|
{
|
|
var command = new TDASCommandPacketBase(new AAFilterCommandString())
|
|
{
|
|
RebuildBytes = true,
|
|
ReplyWait = 0
|
|
};
|
|
baseCommand = command;
|
|
}
|
|
|
|
public AAFilter(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec) : base(sock, timeoutMillisec)
|
|
{
|
|
var command = new TDASCommandPacketBase(new AAFilterCommandString())
|
|
{
|
|
RebuildBytes = true,
|
|
ReplyWait = 0
|
|
};
|
|
baseCommand = command;
|
|
}
|
|
}
|
|
|
|
internal class AAFilterCommandString : CommandString
|
|
{
|
|
/// <summary>
|
|
/// Module Index
|
|
/// </summary>
|
|
public int ModuleIndex { get; set; }
|
|
|
|
/// <summary>
|
|
/// AAFilter Frequency
|
|
/// </summary>
|
|
public float Frequency { get; set; } = 0;
|
|
|
|
protected override string _CommandDescription => "AAFilter";
|
|
|
|
protected override string _CommandString => "F";
|
|
|
|
public AAFilterCommandString()
|
|
{
|
|
RackCommand = true;
|
|
}
|
|
public override byte[] GetParameters()
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.Append(" ");
|
|
sb.Append(ModuleIndex.ToString());
|
|
sb.Append(" ");
|
|
sb.Append(_CommandString);
|
|
sb.Append(" ");
|
|
sb.Append(Frequency.ToString(CultureInfo.InvariantCulture));
|
|
|
|
return Encoding.ASCII.GetBytes(sb.ToString());
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// MonditorDataCommandString encapsulates the string parameters for the MD command used with TDAS PRO SIM
|
|
/// </summary>
|
|
internal class MonitorDataCommandString : CommandString
|
|
{
|
|
public string SamplesPerSendString => SamplesPerSend.ToString();
|
|
public int SamplesPerSend { get; set; } = 5;
|
|
|
|
public double SampleRate { get; set; } = 200D;
|
|
|
|
public string SampleRateString => string.Format("{0:0}", SampleRate);
|
|
|
|
// This doesn't actually do anything, but this is the historical value passed
|
|
public string Channels { get; set; } = "01234567";
|
|
|
|
// This doesn't actually do anything, but this is the historical value passed
|
|
public string Seconds { get; set; } = "360000";
|
|
|
|
// This doesn't actually do anything, but this is the historical value passed
|
|
private char _trigger = 'G';
|
|
public char Trigger
|
|
{
|
|
get => _trigger;
|
|
set
|
|
{
|
|
if (value == 'G' || value == 'W') { _trigger = value; }
|
|
else { throw new Exception("Trigger must be 'G' or 'W' " + value); }
|
|
}
|
|
}
|
|
|
|
// This doesn't actually do anything, but this is the historical value passed
|
|
public string TestId { get; set; } = "Test1";
|
|
|
|
protected override string _CommandDescription => "Monitor Data - MD";
|
|
|
|
protected override string _CommandString => "MD";
|
|
|
|
public override byte[] GetParameters()
|
|
{
|
|
System.IO.MemoryStream ms = new System.IO.MemoryStream();
|
|
ms.WriteByte(Convert.ToByte(' '));
|
|
ms.Write(Encoding.ASCII.GetBytes(SamplesPerSendString), 0, SamplesPerSendString.Length);
|
|
ms.WriteByte(Convert.ToByte(' '));
|
|
ms.Write(Encoding.ASCII.GetBytes(SampleRateString), 0, SampleRateString.Length);
|
|
ms.WriteByte(Convert.ToByte(' '));
|
|
ms.Write(Encoding.ASCII.GetBytes(Channels), 0, Channels.Length);
|
|
ms.WriteByte(Convert.ToByte(' '));
|
|
ms.Write(Encoding.ASCII.GetBytes(Seconds), 0, Seconds.Length);
|
|
ms.WriteByte(Convert.ToByte(' '));
|
|
ms.WriteByte(Convert.ToByte(Trigger));
|
|
ms.WriteByte(Convert.ToByte(' '));
|
|
ms.Write(Encoding.ASCII.GetBytes(TestId), 0, TestId.Length);
|
|
return ms.ToArray();
|
|
}
|
|
public MonitorDataCommandString()
|
|
{
|
|
RackCommand = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// MonitorData encapsulates the MD command used with TDAS PRO SIM. See also MonitorDataCommandString
|
|
/// </summary>
|
|
public class MonitorData : CommandBase
|
|
{
|
|
private TDASCommandPacketBase _command => baseCommand as TDASCommandPacketBase;
|
|
|
|
public int ModuleIndex
|
|
{
|
|
get => _command.ModuleIndex;
|
|
set => _command.ModuleIndex = value;
|
|
}
|
|
|
|
public MonitorData(DTS.Common.Interface.DASFactory.ICommunication sock)
|
|
: base(sock)
|
|
{
|
|
baseCommand = new TDASCommandPacketBase(new MonitorDataCommandString());
|
|
}
|
|
public MonitorData(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout)
|
|
: base(sock, msTimeout)
|
|
{
|
|
baseCommand = new TDASCommandPacketBase(new MonitorDataCommandString());
|
|
}
|
|
public void Execute()
|
|
{
|
|
Execute(CommandCallback, this);
|
|
}
|
|
public CommandReceiveAction CommandCallback(ICommandReport report)
|
|
{
|
|
return CommandReceiveAction.ContinueReceiving;
|
|
}
|
|
}
|
|
|
|
//PROSIM "MD 5 200 01234567 360000 G TEST1";
|
|
//PRODIM static const char* pPRODIMMDCommand = "MD 1000 50 01234567 360000 G TEST1";
|
|
|
|
internal class ProMonitorDataCommandString : MonitorDataCommandString
|
|
{
|
|
protected override string _CommandDescription => "Monitor Data (Pro)";
|
|
|
|
protected override string _CommandString => "MD";
|
|
|
|
public ProMonitorDataCommandString(bool bSIM)
|
|
{
|
|
if (bSIM)
|
|
{
|
|
SamplesPerSend = 5;
|
|
SampleRate = 200D;
|
|
}
|
|
else
|
|
{
|
|
SamplesPerSend = 1000;
|
|
SampleRate = 50;
|
|
}
|
|
RackCommand = false;
|
|
}
|
|
|
|
}
|
|
/// <summary>
|
|
/// The G5MonitorDataCommandString class encapsulates the MDX string parameters used with G5MonitorDataCommand
|
|
/// </summary>
|
|
internal class G5MonitorDataCommandString : MonitorDataCommandString
|
|
{
|
|
protected override string _CommandDescription => "Monitor Data Extended - MDX";
|
|
|
|
protected override string _CommandString => "MDX";
|
|
|
|
public G5MonitorDataCommandString()
|
|
{
|
|
SamplesPerSend = 10;
|
|
SampleRate = 1000D;
|
|
RackCommand = false;
|
|
}
|
|
}
|
|
|
|
public class ProMonitorData : MonitorData
|
|
{
|
|
public ProMonitorData(DTS.Common.Interface.DASFactory.ICommunication sock, bool bSIM)
|
|
: base(sock)
|
|
{
|
|
baseCommand = new TDASCommandPacketBase(new ProMonitorDataCommandString(bSIM));
|
|
}
|
|
public ProMonitorData(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout, bool bSIM)
|
|
: base(sock, msTimeout)
|
|
{
|
|
baseCommand = new TDASCommandPacketBase(new ProMonitorDataCommandString(bSIM));
|
|
}
|
|
/// <summary>
|
|
/// The number of characters in the string for each sample/channel.
|
|
/// </summary>
|
|
private readonly int CharactersPerSample = 4;
|
|
|
|
private short[] _rtData;
|
|
public short[] RTData
|
|
{
|
|
get
|
|
{
|
|
if (null != _rtData) return _rtData;
|
|
// This parses the actual response into ResponseData.
|
|
ProcessData();
|
|
|
|
// Split the faux time stamp (0.0) from the sample data.
|
|
var tokens = ResponseData.Split(' ');
|
|
var data = new List<short>();
|
|
|
|
// Parse the string into 4 byte chunks, one for each channel
|
|
for (var currentOffset = 0; currentOffset < tokens[1].Length; currentOffset += CharactersPerSample)
|
|
{
|
|
var currentSample = tokens[1].Substring(currentOffset, CharactersPerSample);
|
|
int ignoredCharacters;
|
|
var sampleBytes = HexEncoding.GetBytes(currentSample, out ignoredCharacters);
|
|
data.Add((short)(sampleBytes[0] * 256 + sampleBytes[1]));
|
|
}
|
|
_rtData = data.ToArray();
|
|
return _rtData;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// G5MonitorData encapsulates the MDX command used by the TDAS G5
|
|
/// </summary>
|
|
public class G5MonitorData : MonitorData
|
|
{
|
|
public G5MonitorData(DTS.Common.Interface.DASFactory.ICommunication sock)
|
|
: base(sock)
|
|
{
|
|
baseCommand = new TDASCommandPacketBase(new G5MonitorDataCommandString());
|
|
}
|
|
public G5MonitorData(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout)
|
|
: base(sock, msTimeout)
|
|
{
|
|
baseCommand = new TDASCommandPacketBase(new G5MonitorDataCommandString());
|
|
}
|
|
|
|
// The response format is 0.0 XXXXYYYY...ZZZZ
|
|
// Where XXXX is the ADC value for the first channel, YYYY is the second channel and ZZZZ is the last channel which will be the second digital input.
|
|
// There are 34 channels total (32 analog + 2 digital), 4 * 34 = 136 bytes long plus the four for 0.0 and the space making a total of 140 characters.
|
|
|
|
/// <summary>
|
|
/// The number of characters in the string for each sample/channel.
|
|
/// </summary>
|
|
private readonly int CharactersPerSample = 4;
|
|
|
|
|
|
private short[] _rtData;
|
|
/// <summary>
|
|
/// The received real time data in channel order.
|
|
/// </summary>
|
|
public short[] RTData
|
|
{
|
|
get
|
|
{
|
|
if (null != _rtData) return _rtData;
|
|
// This parses the actual response into ResponseData.
|
|
ProcessData();
|
|
|
|
// Split the faux time stamp (0.0) from the sample data.
|
|
var tokens = ResponseData.Split(' ');
|
|
var data = new List<short>();
|
|
|
|
// Parse the string into 4 byte chunks, one for each channel
|
|
for (var currentOffset = 0; currentOffset < tokens[1].Length; currentOffset += CharactersPerSample)
|
|
{
|
|
var currentSample = tokens[1].Substring(currentOffset, CharactersPerSample);
|
|
int ignoredCharacters;
|
|
var sampleBytes = HexEncoding.GetBytes(currentSample, out ignoredCharacters);
|
|
data.Add((short)(sampleBytes[0] * 256 + sampleBytes[1]));
|
|
}
|
|
_rtData = data.ToArray();
|
|
return _rtData;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class G5MonitorDataNextSampleCommandString : MonitorDataCommandString
|
|
{
|
|
protected override string _CommandDescription => "Monitor Data Extended - MDX";
|
|
|
|
protected override string _CommandString => "MDX";
|
|
|
|
public G5MonitorDataNextSampleCommandString()
|
|
{
|
|
RackCommand = false;
|
|
}
|
|
}
|
|
internal class ProMonitorDataNextSampleCommandString : MonitorDataCommandString
|
|
{
|
|
protected override string _CommandDescription => "Monitor Data (Pro) - MD";
|
|
|
|
protected override string _CommandString => "MD";
|
|
|
|
public ProMonitorDataNextSampleCommandString()
|
|
{
|
|
RackCommand = false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// The MDX command sends it's response, then continuously spews out additional response data. This command consumes the additional responses
|
|
/// without sending anything.
|
|
/// </summary>
|
|
public class MonitorDataNextSampleBase : CommandBase
|
|
{
|
|
public enum MonitorType { Pro, G5, DIM };
|
|
private MonitorType _type;
|
|
public MonitorDataNextSampleBase(DTS.Common.Interface.DASFactory.ICommunication sock, MonitorType type)
|
|
: base(sock)
|
|
{
|
|
_type = type;
|
|
switch (type)
|
|
{
|
|
case MonitorType.G5: baseCommand = new TDASCommandPacketBase(new G5MonitorDataNextSampleCommandString()) { MonitorDataMode = true }; break;
|
|
case MonitorType.Pro:
|
|
case MonitorType.DIM:
|
|
baseCommand = new TDASCommandPacketBase(new ProMonitorDataNextSampleCommandString()) { MonitorDataMode = true }; break;
|
|
}
|
|
|
|
}
|
|
public MonitorDataNextSampleBase(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout, MonitorType type)
|
|
: base(sock, msTimeout)
|
|
{
|
|
_type = type;
|
|
switch (type)
|
|
{
|
|
case MonitorType.G5: baseCommand = new TDASCommandPacketBase(new G5MonitorDataNextSampleCommandString()); break;
|
|
case MonitorType.Pro:
|
|
case MonitorType.DIM:
|
|
baseCommand = new TDASCommandPacketBase(new ProMonitorDataNextSampleCommandString()); break;
|
|
}
|
|
}
|
|
private readonly List<byte> _leftOverData = new List<byte>();
|
|
|
|
protected override void ProcessData()
|
|
{
|
|
var response = baseResponse as TDASCommandPacketBase;
|
|
if (null == response) { return; }
|
|
var bytes = new List<byte>(_leftOverData);
|
|
_leftOverData.Clear();
|
|
bytes.AddRange(response.ToBytes());
|
|
string s = Encoding.ASCII.GetString(bytes.ToArray());
|
|
TDASCommandPacketBase command = baseCommand as TDASCommandPacketBase;
|
|
var start = s.IndexOf(command.GetCommandString(0));
|
|
var end = s.LastIndexOf("\r\n");
|
|
if (start < end && start >= 0)
|
|
{
|
|
var csLength = command.GetCommandString(0).Length + 1;
|
|
_responseData = s.Substring(start + csLength, end - start - csLength).TrimStart();
|
|
if (IsErrored()) { throw new InvalidOperationException(_responseData); }
|
|
}
|
|
else { _responseData = ""; }
|
|
}
|
|
|
|
private readonly int CharactersPerSample = 4;
|
|
private List<short[]> _rtData;
|
|
private List<double> _times = new List<double>();
|
|
public double[] Times => _times.ToArray();
|
|
|
|
public List<short[]> RTData
|
|
{
|
|
get
|
|
{
|
|
_rtData = new List<short[]>();
|
|
_times = new List<double>();
|
|
ProcessData();
|
|
|
|
// There is a good chance we'll get multiple lines in one response
|
|
|
|
var lines = ResponseData.Split('\n');
|
|
|
|
// Because the G5 is sending data as fast as it can with no flow control, it's possible that we might fall behind and data may be dropped.
|
|
// As a result there are a few safety checks to skip over partial reads.
|
|
// this particular check doesn't seem helpful for PRO
|
|
if (1 == lines.Length && 140 != lines[0].Length && _type == MonitorType.G5)
|
|
{
|
|
_leftOverData.AddRange(Encoding.ASCII.GetBytes(lines[0]));
|
|
return _rtData;
|
|
}
|
|
|
|
for (var iLine = 0; iLine < lines.Length; iLine++)
|
|
{
|
|
var currentLine = lines[iLine];
|
|
if (string.IsNullOrWhiteSpace(currentLine)) { continue; }
|
|
var index = currentLine.IndexOf("MD");
|
|
switch (_type)
|
|
{
|
|
case MonitorType.G5:
|
|
if (index >= 0) { currentLine = currentLine.Substring(index + 5); }
|
|
break;
|
|
case MonitorType.Pro:
|
|
case MonitorType.DIM:
|
|
if (index >= 0) { currentLine = currentLine.Substring(index + 4); }
|
|
break;
|
|
}
|
|
|
|
var tokens = currentLine.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
|
|
var data = new List<short>();
|
|
var times = new List<double>();
|
|
switch (_type)
|
|
{
|
|
case MonitorType.G5:
|
|
{
|
|
// Partial line, bogus line, or trailing empty line, if it's the last line in the data, we add it back in the buffer for next time
|
|
if (2 != tokens.Length)
|
|
{
|
|
if (iLine == lines.Length - 1) { _leftOverData.AddRange(Encoding.ASCII.GetBytes(lines[iLine])); }
|
|
continue;
|
|
}
|
|
if (137 != tokens[1].Length)
|
|
{
|
|
if (iLine == lines.Length - 1) { _leftOverData.AddRange(Encoding.ASCII.GetBytes(lines[iLine])); }
|
|
continue;
|
|
}
|
|
// Intentionally drop the second to last sample. It's the second bank of digital channels which aren't exposed through a VDS.
|
|
tokens[1] = tokens[1].Substring(0, tokens[1].Length - CharactersPerSample - 5) + tokens[1].Substring(tokens[1].Length - CharactersPerSample - 1, 4);
|
|
for (var currentOffset = 0; currentOffset <= tokens[1].Length - CharactersPerSample; currentOffset += CharactersPerSample)
|
|
{
|
|
var currentSample = tokens[1].Substring(currentOffset, CharactersPerSample);
|
|
int ignoredCharacters;
|
|
var sampleBytes = HexEncoding.GetBytes(currentSample, out ignoredCharacters);
|
|
data.Add((short)(sampleBytes[0] * 256 + sampleBytes[1]));
|
|
}
|
|
}
|
|
break;
|
|
case MonitorType.DIM:
|
|
{
|
|
if (5 != tokens.Length)
|
|
{
|
|
if (iLine == lines.Length - 1)
|
|
{
|
|
_leftOverData.AddRange(Encoding.ASCII.GetBytes(lines[iLine]));
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
double d;
|
|
times.Add(double.TryParse(tokens[0], out d) ? d : 0D);
|
|
try
|
|
{
|
|
var s = string.Concat(tokens[1], tokens[2], tokens[3], tokens[4]);
|
|
s = s.Replace("\r", "");
|
|
s = new string(s.Reverse().ToArray());
|
|
var val = Convert.ToInt16(s, 2);
|
|
data.Add(val);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log(ex);
|
|
data.Add(0);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case MonitorType.Pro:
|
|
{
|
|
if (9 != tokens.Length)
|
|
{
|
|
if (iLine == lines.Length - 1)
|
|
{
|
|
_leftOverData.AddRange(Encoding.ASCII.GetBytes(lines[iLine]));
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (double.TryParse(tokens[0], out double d))
|
|
{
|
|
times.Add(d);
|
|
}
|
|
for (var i = 1; i < tokens.Length; i++)
|
|
{
|
|
var currentSample = tokens[i].Replace("\n", "").Replace("+", "");
|
|
data.Add(short.TryParse(currentSample, out short newdata)
|
|
? newdata
|
|
: short.MinValue);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
_rtData.Add(data.ToArray());
|
|
_times.AddRange(times.ToArray());
|
|
}
|
|
return _rtData;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// We need to override SyncExecute because we don't want to send anything (that would tell the G5 to stop sending). Instead we just want to
|
|
/// read whatever is out there. Otherwise this is mostly cut and paste of normal SyncExecute with some streamlining for our specific case.
|
|
/// </summary>
|
|
public override void SyncExecute()
|
|
{
|
|
// this is a try/finally to handle the ExecuteIsBusy
|
|
try
|
|
{
|
|
// there can be only one!
|
|
recorder.ExecuteIsBusy = true;
|
|
|
|
if (recorder.IsCanceled())
|
|
{
|
|
throw new CanceledException();
|
|
}
|
|
|
|
UserCallback = null;
|
|
UserCallbackData = null;
|
|
IsSynchronous = true;
|
|
SyncEvent.Reset();
|
|
recorder.PseudoExecute(new byte[0], ExecuteCallback, null, IO_Timeout);
|
|
|
|
var syncExecTimeout = IO_Timeout;
|
|
|
|
try
|
|
{
|
|
if (!WaitWithCondition.Wait(SyncEvent, syncExecTimeout, recorder.CancelEvent))
|
|
{
|
|
// timeout
|
|
LogString("SyncExecute: timeout");
|
|
throw new TimeoutException(MakeLogString("SyncExecute: timeout"));
|
|
}
|
|
}
|
|
catch (WaitWithCondition.ConditionMetException)
|
|
{
|
|
throw new CanceledException();
|
|
}
|
|
|
|
// we didn't timeout, check the result
|
|
switch (ComReport.Result)
|
|
{
|
|
case CommunicationConstantsAndEnums.CommunicationResult.Canceled:
|
|
throw new CanceledException();
|
|
|
|
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveOK:
|
|
if (baseResponse == null)
|
|
{
|
|
LogString("SyncExecute: ReceiveOK but response==null!");
|
|
LogCommand(false);
|
|
throw new Exception(MakeLogString("SyncExecute: ReceiveOK but response==null!"));
|
|
}
|
|
|
|
if (baseResponse.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
|
|
{
|
|
// didn't go well
|
|
var msg = MakeLogString("SyncExecute: response.Status = " + baseResponse.Status.ToString());
|
|
LogCommand(false);
|
|
if (baseResponse.Status == DFConstantsAndEnums.CommandStatus.StatusInvalidModeForCommand)
|
|
{
|
|
throw new CommandException(CommandErrorReason.InvalidMode, msg);
|
|
}
|
|
if (baseResponse.Status == DFConstantsAndEnums.CommandStatus.StatusUnimplemented ||
|
|
baseResponse.Status == DFConstantsAndEnums.CommandStatus.StatusInvalidCommand ||
|
|
baseResponse.Status == DFConstantsAndEnums.CommandStatus.StatusInvalidCommandType)
|
|
{
|
|
throw new NotImplementedException(msg);
|
|
}
|
|
var ex = new Exception(msg);
|
|
ex.Data.Add("Status", baseResponse.Status);
|
|
throw ex;
|
|
}
|
|
|
|
// everything is fine, let it exit
|
|
if (LogCommands)
|
|
{
|
|
LogCommand(false);
|
|
}
|
|
break;
|
|
|
|
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveFailed:
|
|
{
|
|
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result.ToString());
|
|
LogCommand(false);
|
|
|
|
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
|
|
}
|
|
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveTimeout:
|
|
{
|
|
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result.ToString());
|
|
LogCommand(false);
|
|
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
|
|
}
|
|
|
|
case CommunicationConstantsAndEnums.CommunicationResult.SendFailed:
|
|
case CommunicationConstantsAndEnums.CommunicationResult.SendTimeout:
|
|
{
|
|
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result.ToString());
|
|
LogCommand(false);
|
|
throw new CommandException(CommandErrorReason.SendFailed, msg);
|
|
}
|
|
|
|
default:
|
|
{
|
|
var msg = MakeLogString("SyncExecute: Unknown ComReport.Result == " + ComReport.Result.ToString());
|
|
LogCommand(false);
|
|
throw new Exception(msg);
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
recorder.ExecuteIsBusy = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
internal class QuitG5CommandString : CommandString
|
|
{
|
|
protected override string _CommandString => "Q";
|
|
|
|
protected override string _CommandDescription => "Quit Monitoring Data - Q";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Use QuitMonitoring to halt realtime data from a G5 or TDAS PRO SIM
|
|
/// </summary>
|
|
public class QuitG5Monitoring : CommandBase
|
|
{
|
|
public int ModuleIndex { set => ((TDASCommandPacketBase)baseCommand).ModuleIndex = value; }
|
|
|
|
public QuitG5Monitoring(DTS.Common.Interface.DASFactory.ICommunication sock)
|
|
: base(sock)
|
|
{
|
|
baseCommand = new TDASCommandPacketBase(new QuitG5CommandString());
|
|
}
|
|
public QuitG5Monitoring(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout)
|
|
: base(sock, msTimeout)
|
|
{
|
|
baseCommand = new TDASCommandPacketBase(new QuitG5CommandString());
|
|
}
|
|
}
|
|
internal class SingleSampleCommandString : CommandString
|
|
{
|
|
protected override string _CommandString => "SS";
|
|
|
|
protected override string _CommandDescription => "Single Sample - SS";
|
|
}
|
|
|
|
/// <summary>
|
|
/// The SingleSample command is used with either a TDAS G5 or TDAS PRO SIM to take a single measurement for all channels.
|
|
/// </summary>
|
|
public class SingleSample : CommandBase
|
|
{
|
|
private short[] _rtData;
|
|
public short[] RTData
|
|
{
|
|
get
|
|
{
|
|
if (null != _rtData) return _rtData;
|
|
ProcessData();
|
|
var tokens = ResponseData.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
|
var data = new List<short>();
|
|
foreach (var token in tokens)
|
|
{
|
|
if (short.TryParse(token, out short temp) && data.Count < 8)
|
|
{
|
|
data.Add(temp);
|
|
}
|
|
else
|
|
{
|
|
//digital channels are always included with G5, and we already have 8 values, so ... chances are it's the digital bits
|
|
if (!int.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture,
|
|
out int i)) continue;
|
|
data.Add((short)i);
|
|
data.Add((short)(i >> 16));
|
|
}
|
|
}
|
|
_rtData = data.ToArray();
|
|
return _rtData;
|
|
}
|
|
}
|
|
private TDASCommandPacketBase _command => baseCommand as TDASCommandPacketBase;
|
|
|
|
public int ModuleIndex
|
|
{
|
|
get => _command.ModuleIndex;
|
|
set => _command.ModuleIndex = value;
|
|
}
|
|
|
|
public SingleSample(DTS.Common.Interface.DASFactory.ICommunication sock)
|
|
: base(sock)
|
|
{
|
|
baseCommand = new TDASCommandPacketBase(new SingleSampleCommandString());
|
|
}
|
|
public SingleSample(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout)
|
|
: base(sock, msTimeout)
|
|
{
|
|
baseCommand = new TDASCommandPacketBase(new SingleSampleCommandString());
|
|
}
|
|
}
|
|
}
|