This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1,233 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using DTS.DASLib.Command.Classes;
using DTS.Common.Utilities.Logging;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Enums.DASFactory;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
/// <summary>
/// 10558 Auto-discovery to add cmd/res support for MAC table
/// </summary>
public class MulticastDiscoverSlice6 : MulticastCommandBase
{
#region constants and enums
private const int COMMAND_PAYLOAD_SIZE = 80;
private const int DEVICE_CLASS_OFFSET = 36;
private const int NUMBER_OF_RECORDS_OFFSET = 40;
private const int RESERVED_OFFSET = 42;
private const int START_OF_MAC_TABLE = 48;
private const int SIZE_OF_MAC_RECORD = 12;//bytes
private const int PORT_OFFSET = 2;
private const int FILTER_OFFSET = 4;
private const int MAC_OFFSET = 6;
#endregion
#region private properties
protected override Commands Command => Commands.GetMACTable;
protected override bool StopAfterFirstMessage => false;
private uint _deviceClass;
private byte _responseOption;
private IPAddress _address;
private const string RX_MULTICAST_ADDRESS = "239.4.5.6";
private void SetMulticastConfig()
{
IPAddress.TryParse(RX_MULTICAST_ADDRESS, out _address);
}
#endregion
#region public properties
public DeviceClasses DeviceClass { set { _deviceClass = (uint)value; command.SetParameter(36, (int)_deviceClass); } }
public ResponseOptions ResponseOption { set { _responseOption = (byte)value; command.SetParameter(40, _responseOption); } }
public uint DesiredPort
{
set => command.SetParameter(41, value);
}
public byte[] MACFilter
{
set => command.SetParameter(45, value);
}
public TextLogger Logger { get; set; }
public Dictionary<string, IDiscoveredDevice> MACAddressToDevice { get; set; }
private readonly List<DiscoveredConnectedSlice> _connectedDevices = new List<DiscoveredConnectedSlice>();
public DiscoveredConnectedSlice[] ConnectedDevices => _connectedDevices.ToArray();
#endregion
#region constructors and initializers
public MulticastDiscoverSlice6(DeviceClasses deviceClass, string hostMac)
: base(null)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
HostMac = hostMac;
DeviceClass = deviceClass;
ResponseOption = ResponseOptions.AlwaysRespond;
SetMulticastConfig();
DesiredPort = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3;
MACFilter = new[]
{
Convert.ToByte(0x00),
Convert.ToByte(0x19),
Convert.ToByte(0x9b),
byte.MaxValue,
byte.MaxValue,
byte.MaxValue
};
}
public MulticastDiscoverSlice6(string hostMac, int timeoutMillisec)
: base(null, timeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
HostMac = hostMac;
DeviceClass = DeviceClasses.Any;
ResponseOption = ResponseOptions.AlwaysRespond;
SetMulticastConfig();
DesiredPort = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3;//ports 1-4
MACFilter = new[]
{
Convert.ToByte(0x00),
Convert.ToByte(0x19),
Convert.ToByte(0x9b),
byte.MaxValue,
byte.MaxValue,
byte.MaxValue
};
}
#endregion
#region methods
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
response.GetParameter(HOST_MAC_ADDRESS_OFFSET, out ResponseHostMac);
if (null == ResponseHostMac || !HostMac.Equals(ResponseHostMac))
{
response.Status = DFConstantsAndEnums.CommandStatus.StatusInvalidPacket;
return CommandReceiveAction.StopReceiving;
}
response.GetParameter(CLIENT_MAC_ADDRESS_OFFSET, out ResponseClientMac);
response.GetParameter(DEVICE_CLASS_OFFSET, out _deviceClass);
ushort numberOfEntries;
response.GetParameter(NUMBER_OF_RECORDS_OFFSET, out numberOfEntries);
var list = new List<MACTableEntry>();
for (var i = 0; i < numberOfEntries; i++)
{
try
{
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD, out ushort age);
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD + PORT_OFFSET, out ushort port);
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD + FILTER_OFFSET, out ushort filter);
var mac = new byte[6];
for (var b = 0; b < mac.Length; b++)
{
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD + MAC_OFFSET + b, out byte thisByte);
mac[b] = thisByte;
}
list.Add(new MACTableEntry(age, port, filter, mac));
}
catch (Exception ex)
{
APILogger.Log($"MulticastDiscoverSlice6 failed to get entry - ignoring entry", ex.Message);
}
}
_connectedDevices.Add(new DiscoveredConnectedSlice(ResponseClientMac, list.ToArray()));
var responseMac = ResponseClientMac.Replace('-', ':').ToUpper();
var serialNumber = "N/A";
if (null != MACAddressToDevice && MACAddressToDevice.ContainsKey(responseMac))
{
serialNumber = MACAddressToDevice[responseMac].Serial;
}
Log(ResponseHostMac, ResponseClientMac, list.ToArray(), serialNumber);
//Log(response.Parameter);
return CommandReceiveAction.StopReceiving;
}
private static string ByteToHex(byte b)
{
return $"{b:x2}";
}
private void Log(IReadOnlyList<byte> parameter)
{
var sb = new StringBuilder();
sb.Append("msg: ");
foreach (var b in parameter)
{
sb.Append(ByteToHex(b));
}
sb.AppendLine();
//var bytes = new List<byte>(parameter);
sb.Append("header: ");
for (var i = 0; i < START_OF_MAC_TABLE; i++)
{
sb.Append(ByteToHex(parameter[i]));
}
sb.AppendLine();
for (var i = START_OF_MAC_TABLE; i < parameter.Count; i += SIZE_OF_MAC_RECORD)
{
sb.Append("Record: ");
for (var idx = 0; idx < SIZE_OF_MAC_RECORD; idx++)
{
sb.Append(ByteToHex(parameter[i + idx]));
}
sb.AppendLine();
}
Log(sb.ToString());
}
private void Log(string responseHostMac, string responseClientMac, MACTableEntry[] entries, string serialNumber)
{
var sb = new StringBuilder();
sb.AppendFormat("Host: {0}, Client: {1}, SerialNumber: {2}", responseHostMac, responseClientMac, serialNumber);
sb.AppendLine();
sb.AppendLine("Age\tFilter\tMAC\t\t\tPort");
foreach (var entry in entries)
{
sb.AppendFormat("{0}\t{1}\t{2}\t{3}", entry.Age, entry.Filter, MACAddressToString(entry.MAC), entry.Port);
sb.AppendLine();
}
Log(sb.ToString());
}
public static string MACAddressToString(IEnumerable<byte> mac)
{
var list = mac.Select(b => $"{b:x2}").ToList();
return string.Join(":", list.ToArray()).ToUpper();
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"AutoDiscover: [{HostMac}]" });
}
private void Log(string msg)
{
if (null == Logger) { return; }
Logger.LogMessage($"====={DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}=====\r\n");
Logger.LogMessage(msg);
}
#endregion
}
}

View File

@@ -0,0 +1,96 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// Retrieves parameters of Ethernet data recorder by EthernetRecorder
/// </summary>
public class QueryEthernetEventInfo : EventDataCommands
{
protected override Commands Command => Commands.QueryEthernetEventInfo;
private ushort _eventID = 0;
public ushort EventID
{
get { return _eventID; }
set { _eventID = value; command.SetParameter(0, _eventID); }
}
private ushort _dataDownloaded = 0;
public ushort DataDownloaded => _dataDownloaded;
private ulong _totalByteCount = 0UL;
public ulong TotalByteCount => _totalByteCount;
private ulong _triggerByteCount = 0UL;
public ulong TriggerByteCount => _triggerByteCount;
private ulong _faultByteCount;
public ulong FaultByteCount => _faultByteCount;
private uint[] _DataStartTimeStamp = new uint[] { 0, 0 };
public uint[] DataStartTimeStamp => _DataStartTimeStamp;
public QueryEthernetEventInfo(ICommunication sock)
: base(sock)
{
//Command Parameters: 4 bytes.
//Byte[1:0] U16 Event ID.
//Byte[3:2]: Reserved.
command.Parameter = new byte[4];
}
public QueryEthernetEventInfo(ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
//Command Parameters: 4 bytes.
//Byte[1:0] U16 Event ID.
//Byte[3:2]: Reserved.
command.Parameter = new byte[4];
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
if (response.ParameterLength > 0)
{
/*
Response: 36 bytes.
Byte [1:0] U16 Event ID.
Byte [3:2] U16 Data Downloaded Flag.
Byte [11:4] U64 Total ByteCount.
Byte [19:12] U64 Trigger ByteCount.
Byte [27:20] U64 Fault ByteCount.
Byte [35:28] U32[2] Data Start Timestamp. U32[0] = Second. U32[1] = Nano-Second
*/
response.GetParameter(0, out _eventID);
response.GetParameter(2, out _dataDownloaded);
response.GetParameter(4, out _totalByteCount);
response.GetParameter(12, out _triggerByteCount);
response.GetParameter(20, out _faultByteCount);
response.GetParameter(28, out uint temp);
_DataStartTimeStamp[0] = temp;
response.GetParameter(32, out temp);
_DataStartTimeStamp[1] = temp;
}
else { _eventID = 0; }
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"EventId: {EventID}",
$"DataDownloaded: {DataDownloaded}",
$"TotalByteCount: {TotalByteCount}",
$"TriggerByteCount: {TriggerByteCount}",
$"FaultByteCount: {FaultByteCount}",
$"DataStartTimeStamp: {DataStartTimeStamp[0]}, {DataStartTimeStamp[1]}"
});
}
}
}

View File

@@ -0,0 +1,226 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using DTS.DASLib.Command.Classes;
using DTS.Common.Utilities.Logging;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastAutoDiscover : MulticastCommandBase
{
#region constants and enums
private const int COMMAND_PAYLOAD_SIZE = 63;
private const int RESPONSE_PAYLOAD_SIZE = 278;
#endregion
#region private/protected properties
protected override Commands Command => Commands.AutoDiscover;
protected override bool StopAfterFirstMessage => false;
private uint _deviceClass;
private byte _responseOption;
private IPAddress _address;
private int _port = (int)Ports.Response;
private byte _dhcpEnabled;
private string _ip;
private string _subnet;
private string _gateway;
private string _dns;
private byte _isConnected;
private string _connectedIp;
private ushort _id;
private string _serialNumber;
private string _location;
private string _version;
private string _buildId;
#endregion
#region public properties
public List<IDiscoveredDevice> DiscoveredDevices { get; } = new List<IDiscoveredDevice>();
public TextLogger Logger { get; set; }
public DFConstantsAndEnums.MultiCastDeviceClasses DeviceClass { set { _deviceClass = (uint)value; command.SetParameter(36, (int)_deviceClass); } }
public ResponseOptions ResponseOption { set { _responseOption = (byte)value; command.SetParameter(40, _responseOption); } }
public IPAddress Address { set { _address = value; SetMulticastConfig(); } }
#endregion
#region methods
private void SetMulticastConfig()
{
IPAddress.TryParse(MulticastReceiveAddress, out _address);
var config = $"{_address}:{ResponsePort}";
command.SetParameter(41, config);
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
response.GetParameter(HOST_MAC_ADDRESS_OFFSET, out ResponseHostMac);
//we want to accept the response - even if it was sent on a
//a different mac address ...
if (response.ParameterLength < RESPONSE_PAYLOAD_SIZE)
{
response.Status = DFConstantsAndEnums.CommandStatus.StatusAttributeInvalidLength;
return CommandReceiveAction.StopReceiving;
}
response.GetParameter(CLIENT_MAC_ADDRESS_OFFSET, out ResponseClientMac);
response.GetParameter(36, out _deviceClass);
response.GetParameter(40, out _dhcpEnabled);
response.GetParameter(41, out _ip);
response.GetParameter(57, out _subnet);
response.GetParameter(73, out _gateway);
response.GetParameter(89, out _dns);
response.GetParameter(105, out _id);
response.GetParameter(107, out _isConnected);
response.GetParameter(108, out _serialNumber);
response.GetParameter(118, out _location);
response.GetParameter(198, out _version);
response.GetParameter(230, out _buildId);
response.GetParameter(262, out _connectedIp);
var sb = new StringBuilder();
//String.Format("{0,-27}", s);
sb.AppendFormat("SerialNumber {0}\r\n", _serialNumber);
sb.AppendFormat("ResponseClientMac {0}\r\n", ResponseClientMac);
sb.AppendFormat("IP {0}\r\n", _ip);
sb.AppendFormat("Location {0}\r\n", _location);
sb.AppendFormat("Id {0}\r\n", _id);
sb.AppendFormat("Version {0}\r\n", _version);
sb.AppendFormat("BuildId {0}\r\n", _buildId);
Log(sb.ToString());
var slice = new DiscoveredDevice
{
Mac = ResponseClientMac.Replace('-', ':'),
DevClass = (DFConstantsAndEnums.MultiCastDeviceClasses)_deviceClass,
Dhcp = Convert.ToBoolean(_dhcpEnabled),
Ip = _ip,
Subnet = _subnet,
Gateway = _gateway,
Dns = _dns,
SystemId = _id,
Connected = Convert.ToBoolean(_isConnected)
};
try
{
if (slice.DevClass == DFConstantsAndEnums.MultiCastDeviceClasses.S6DB ||
slice.DevClass == DFConstantsAndEnums.MultiCastDeviceClasses.Slice6)
{
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
slice.ConnectedIp = _connectedIp;
if (string.Empty != _connectedIp)
{
try
{
IPAddress connectedAddress;
IPAddress.TryParse(_connectedIp, out connectedAddress);
var hostName = Dns.GetHostEntry(connectedAddress);
slice.ConnectedHost = hostName.HostName;
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
slice.Serial = _serialNumber;
slice.Location = _location;
slice.FirmwareVersion = _version;
slice.BuildId = _buildId;
DiscoveredDevices.Add(slice);
return CommandReceiveAction.StopReceiving;
}
// ReSharper disable once InconsistentNaming
private static ConnectedEthernetDevice[] ParseSSIData(string data, DFConstantsAndEnums.MultiCastDeviceClasses type)
{
var connections = new List<ConnectedEthernetDevice>();
var lines = data.Replace("\r", "").Split('\n');
foreach (var line in lines)
{
var columns = line.Split(',');
if (columns.Length < 4) { continue; }
if (!char.IsNumber(columns[0][0])) { continue; }
var port = int.Parse(columns[1]);
switch (type)
{
case DFConstantsAndEnums.MultiCastDeviceClasses.Slice6:
if (2 != port) { continue; }
break;
case DFConstantsAndEnums.MultiCastDeviceClasses.S6DB:
if (port > 4) { continue; }
break;
}
var macAddress = columns[3];
connections.Add(new ConnectedEthernetDevice(macAddress, port));
}
return connections.ToArray();
}
private void Log(string msg)
{
if (null == Logger) { return; }
Logger.LogMessage($"====={DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}=====\r\n");
Logger.LogMessage(msg);
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"AutoDiscover: [{HostMac}] {_address} : {_port}" });
}
#endregion
#region constructors and initializers
public MulticastAutoDiscover()
: base(null)
{
Init();
}
public MulticastAutoDiscover(string macAddress)
: base(null)
{
Init(macAddress);
}
public MulticastAutoDiscover(int timeoutMillisec)
: base(null, timeoutMillisec)
{
Init();
}
public MulticastAutoDiscover(string macAddress, int timeoutMillisec)
: base(null, timeoutMillisec)
{
Init(macAddress);
}
public void Init(string macAddress = "")
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
HostMac = string.IsNullOrEmpty(macAddress) ? GetMacAddress() : macAddress;
command.SetParameter(HOST_MAC_ADDRESS_OFFSET, HostMac);
DeviceClass = DFConstantsAndEnums.MultiCastDeviceClasses.Any;
ResponseOption = ResponseOptions.AlwaysRespond;
SetMulticastConfig();
}
#endregion
}
}

View File

@@ -0,0 +1,41 @@
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
public abstract class RealtimeCommandBase : CommandBase
{
protected enum Commands
{
Reserved = 0x00,
StartRealtimeMode = 0x01,
EndRealtimeMode = 0x02,
GetRealtimeSamples = 0x03,
RetrieveSingleSample = 0x04,
RetrieveSampleAverage = 0x05,
RetrieveInternalOffsetSampleAvg = 0x06,
StartRealtimeStreamingMode = 0x07,
GetRealtimeStreamSamples = 0x08,
StartTimeStampStreamMode = 0x09, // CMDRT_START_TIMESTAMPED_STREAM_MODE = 0x09: Start IRIG realtime stream with destination IP address from system attribute
GetTimeStampStreamSamples = 0x0A, // CMDRT_TIMESTAMPED_STREAM_SAMPLES = 0x0A: streaming data from cmd 0x09
ChannelTappedTest = 0x0B,
I106StreamConfigSet = 0x0C, // FB15313 add streaming config options
I106StreamConfigGet = 0x0D,
};
protected abstract Commands _Command { get; }
protected RealtimeCommandBase(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.Realtime;
command.SetCommand((byte)_Command, _Command.ToString());
}
protected RealtimeCommandBase(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Type = CommandPacket.CommandType.Realtime;
command.SetCommand((byte)_Command, _Command.ToString());
}
}
}

View File

@@ -0,0 +1,42 @@
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public abstract class EventDataCommands : CommandBase
{
protected enum Commands
{
Reserved = 0x00,
ResetEventList = 0x01,
QueryTotalEventCount = 0x02,
QueryMatchingEvents = 0x03,
QueryEventData = 0x04,
SetEventData = 0x05,
StartDownloadStreamData = 0x06, // CMDEVD_STREAM_EVENT_DATA_START
GetNextDownloadStreamDataSamples = 0x07, // stream packet of data out to receiver.
QueryUartEventInfo = 0x09, // saved UART info
QueryUartEventData = 0x0A,
SetUartEventData = 0x0B,
GenerateEvent = 0x0C,
QueryEthernetEventInfo = 0x0D,
QueryEthernetEventData = 0x0E,
SetEthernetEventData = 0x0F
};
protected abstract Commands Command { get; }
protected EventDataCommands(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.EventData;
command.SetCommand((byte)Command, Command.ToString());
}
protected EventDataCommands(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Type = CommandPacket.CommandType.EventData;
command.SetCommand((byte)Command, Command.ToString());
}
}
}

View File

@@ -0,0 +1,166 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
/// <summary>
/// this class handles decoding a SPS realtime stream packet.
/// </summary>
public class RealtimeStreamDecoder
{
/* per lp,
* Byte index:
0 Sync = CMD_SYNC_BYTE = 0xFA
1 type = CMD_TYPE_REALTIME = 0x08
2 command = CMDRT_REALTIME_STREAM_SAMPLE_PUSH = 0x08
3 status = STATUS_ERROR_NONE = 0x00
4 group = 0x00;
5 id = 0x00;
6-7 datalength
8-9 sequence number
10-11 headerCRC16
12-13 dataCRC16 (currently not used)
… payload
8-byte uint64_t Timestamp (for first sample in payload.)
4-byte uint32_t Channel list (bit set = channel present. Bit clear = channel not present.
8-byte uint64_t Sample Number (starting with first ADC scan in payload)
Number of ADC-Scan sample = (datalength 20) / (channellist*2)
*/
/// <summary>
/// this is the order of information in the packet
/// the enum value is the offset in bytes from the start of the packet
/// </summary>
public enum ByteIndex
{
Sync = 0,
Type = 1,
Command = 2,
Status = 3,
Group = 4,
Id = 5,
DataLength = 6,
SequenceNumber = 8,
HeaderCRC = 10,
DataCRC = 12,
TimeStamp = 14,
ChannelList = 22,
SampleNumber = 26,
DataStart = 34
}
public ushort SequenceNumber { get; }
public ulong TimeStamp { get; }
public ulong SampleNumber { get; }
public int[] Channels { get; }
/// <summary>
/// this is all data, not transformed into (short) yet, which requires 2's compliment
/// it is also for all channels in the realtime stream
/// </summary>
public ushort[] RtData { get; }
/// <summary>
/// constructors and decodes byte stream
///
/// </summary>
/// <param name="bytes"></param>
public RealtimeStreamDecoder(IReadOnlyList<byte> bytes)
{
if (bytes.Count > (int)ByteIndex.DataStart)
{
TimeStamp = GetULong(bytes, (int)ByteIndex.TimeStamp);
SequenceNumber = GetUShort(bytes, (int)ByteIndex.SequenceNumber);
SampleNumber = GetULong(bytes, (int)ByteIndex.SampleNumber);
RtData = new ushort[(bytes.Count - (int)ByteIndex.DataStart) / 2];
var uintChannelList = GetUINT(bytes, (int)ByteIndex.ChannelList);
var channels = new List<int>();
var ba = new BitArray(BitConverter.GetBytes(uintChannelList));
for (var i = 0; i < ba.Length; i++)
{
if (ba.Get(i))
{
channels.Add(i);
}
}
Channels = channels.ToArray();
for (var idx = 0; idx < RtData.Length; idx++)
{
//all the data is stored as uint16 with channel order so
// AABBCCDDEEFF, so split out the ushorts
RtData[idx] = GetRTUShort(bytes, (int)(ByteIndex.DataStart + idx * 2));
}
}
else
{
RtData = new ushort[0];
SampleNumber = 0;
Channels = new int[0];
}
}
/// <summary>
/// returns a ulong given a sequence of bytes and a starting offset in bytes
/// that the ulong starts at
/// SLICE header bytes are sent in reverse order so we have to fix them first
/// </summary>
/// <param name="bytes"></param>
/// <param name="offset"></param>
/// <returns></returns>
private static ulong GetULong(IReadOnlyList<byte> bytes, int offset)
{
return (ulong)bytes[offset + 7] << 0 |
(ulong)bytes[offset + 6] << 8 |
(ulong)bytes[offset + 5] << 16 |
(ulong)bytes[offset + 4] << 24 |
(ulong)bytes[offset + 3] << 32 |
(ulong)bytes[offset + 2] << 40 |
(ulong)bytes[offset + 1] << 48 |
(ulong)bytes[offset + 0] << 56;
}
/// <summary>
/// gets a ushort from the response parameters
/// SLICE header bytes are sent in reverse order, so we have to fix
/// them first
/// </summary>
/// <param name="bytes"></param>
/// <param name="offset"></param>
/// <returns></returns>
private static uint GetUINT(IReadOnlyList<byte> bytes, int offset)
{
return (uint)bytes[offset + 3] << 0 |
(uint)bytes[offset + 2] << 8 |
(uint)bytes[offset + 1] << 16 |
(uint)bytes[offset + 0] << 32;
}
/// <summary>
/// returns a ushort given a sequence of bytes and a starting offset in bytes
/// SLICE header bytes are sent in reverse order, so we have to fix the byte
/// order first
/// </summary>
/// <param name="bytes"></param>
/// <param name="offset"></param>
/// <returns></returns>
private static ushort GetUShort(IReadOnlyList<byte> bytes, int offset)
{
return (ushort)(bytes[offset + 1] |
bytes[offset + 0] << 8);
}
/// <summary>
/// returns a ushort given a sequence of bytes and a starting offset in bytes
/// note that DATA is not in reverse order unlike the header, so we
/// DON'T need to fix the order
/// </summary>
/// <param name="bytes"></param>
/// <param name="offset"></param>
/// <returns></returns>
private static ushort GetRTUShort(IReadOnlyList<byte> bytes, int offset)
{
return (ushort)(bytes[offset + 0] |
bytes[offset + 1] << 8);
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastGetDnsAddress : MulticastCommandBase
{
protected override Commands Command => Commands.GetDnsAddress;
private string _dns;
public string Dns => _dns;
public MulticastGetDnsAddress(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public MulticastGetDnsAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
base.WholePackage();
response.GetParameter(FIRST_PARAMETER_OFFSET, out _dns);
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} " });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} Dns: {_dns}" });
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastGetSubnetAddress : MulticastCommandBase
{
protected override Commands Command => Commands.GetSubnetAddress;
private string _subnet;
public string Subnet => _subnet;
public MulticastGetSubnetAddress(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public MulticastGetSubnetAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
base.WholePackage();
response.GetParameter(FIRST_PARAMETER_OFFSET, out _subnet);
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} " });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} Subnet: {_subnet}" });
}
}
}

View File

@@ -0,0 +1,117 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// retrieves Ethernet data from an EthernetRecorder
/// </summary>
public class QueryEthernetEventData : EventDataCommands
{
private ushort _eventID = 0;
public ushort EventID
{
get => _eventID;
set { _eventID = value; command.SetParameter(0, _eventID); }
}
protected override Commands Command => Commands.QueryEthernetEventData;
private uint _requestByteCount = 0;
public uint RequestByteCount
{
get => _requestByteCount;
set { _requestByteCount = value; command.SetParameter(2, _requestByteCount); }
}
private ulong _StartDataOffsetBytes = 0UL;
public ulong StartDataOffsetBytes
{
get => _StartDataOffsetBytes;
set { _StartDataOffsetBytes = value; command.SetParameter(6, _StartDataOffsetBytes); }
}
private byte[] _data;
public byte[] Data
{
get => _data;
set
{
if (null == value) { return; }
_data = value;
}
}
private const int PARAMETER_BYTE_COUNT = 14;
public QueryEthernetEventData(ICommunication sock)
: base(sock)
{
command.Parameter = new byte[PARAMETER_BYTE_COUNT];
/*
Byte [1:0] U16 Event ID
Byte [5:2] U32 Request byte count.
Byte [13:6] U64 Start data offset in byte counter.
*/
}
public QueryEthernetEventData(ICommunication sock, int timeoutMS)
: base(sock, timeoutMS)
{
command.Parameter = new byte[PARAMETER_BYTE_COUNT];
/*
Byte [1:0] U16 Event ID
Byte [5:2] U32 Request byte count.
Byte [13:6] U64 Start data offset in byte counter.
*/
}
protected override CommandReceiveAction WholePackage()
{
/*
Byte [1:0]: U16 Event ID
Byte [5:2]: U32 Payload length in byte count.
Byte [13:6]: U64 data offset start.
Byte [payloadLength]: Data byte stream with payload length firmware can fit to a response payload size or that of request whichever less.
*/
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
if (response.ParameterLength > 0)
{
response.GetParameter(0, out _eventID);
response.GetParameter(2, out uint payloadLength);
response.GetParameter(6, out _StartDataOffsetBytes);
_data = new byte[payloadLength];
for (var i = 0; i < payloadLength; i++)
{
response.GetParameter(PARAMETER_BYTE_COUNT + i, out _data[i]);
}
}
else { _eventID = 0; }
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>()
{
$"Event ID: {EventID}",
$"StartDataOffset: {StartDataOffsetBytes}",
$"RequestByteCount: {RequestByteCount}"
});
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"Event ID: {EventID}",
$"Payload(bytes): {_data.Length}",
$"StartDataOffsetBytes: {StartDataOffsetBytes}"
});
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
/// <summary>
/// ported from FWTU, appears almost verbatim to there
/// </summary>
public class UDPStreamPacket
{
/// <summary>
/// first array channels, second array sample index
/// </summary>
public short[][] ChannelData { get; set; }
public long TimeStamp { get; set; }
public ulong SampleNumber { get; set; }
public ulong SequenceNumber { get; set; }
public uint PTPTimesec { get; set; }
public uint PTPTimeNsec { get; set; }
public bool PTPSyncStatusError { get; set; }
public bool ADCOverflowStatus { get; set; }
public string PTPTimeString => string.Concat(PTPTimesec, ":", PTPTimeNsec.ToString("000000000"));
public UDPStreamPacket()
{
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastSetGatewayAddress : MulticastCommandBase
{
const int COMMAND_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE + IP_ADDR_SIZE;
protected override Commands Command => Commands.SetGatewayAddress;
private string _gateway;
public string Gateway { set { _gateway = value; command.SetParameter(FIRST_PARAMETER_OFFSET, _gateway); } }
public MulticastSetGatewayAddress(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public MulticastSetGatewayAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} Gateway: {_gateway}" });
}
}
}

View File

@@ -0,0 +1,61 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
public class GetRealtimeSamplesSLICE6 : GetRealtimeSamples
{
public GetRealtimeSamplesSLICE6(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock) { }
public GetRealtimeSamplesSLICE6(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec) { }
protected override CommandReceiveAction WholePackage()
{
try
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
// Figure out the number of samples returned
var samplesReturned = (response.ParameterLength - 8) / (_channels * 2);
_samplesReturned = samplesReturned;
_data = new List<short[]>(_channels);
// Grab the sample number
if (response.ParameterLength > 0)
{
response.GetParameter(0, out _sampleNumber);
}
// Create the data arrays by channel
for (int i = 0; i < _channels; i++)
{
_data.Add(new short[samplesReturned]);
}
// Grab the data
var parameter = 8;
for (var sample = 0; sample < samplesReturned; sample++)
{
for (var channel = 0; channel < _channels; channel++)
{
response.GetParameter(parameter, out ushort val);
//Slice6 data is signed data. No need to convert.
_data[channel][sample] = (short)((((val & 0x00FF) << 8) | ((val >> 8) & 0x00FF)));
parameter += 2;
}
}
return CommandReceiveAction.StopReceiving;
}
}
catch
{
_samplesReturned = 0;
}
return CommandReceiveAction.StopReceiving;
}
}
}

View File

@@ -0,0 +1,38 @@
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
public class StartRealtimeMode : RealtimeCommandBase
{
private bool _bSupportsMultipleSampleRealtime = true;
public bool SupportsMultipleSampleRealtime
{
get => _bSupportsMultipleSampleRealtime;
set
{
_bSupportsMultipleSampleRealtime = value;
if (value) { command.Parameter = new byte[1]; }
else { command.Parameter = new byte[0]; }
}
}
protected override Commands _Command => Commands.StartRealtimeMode;
public StartRealtimeMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
// don't need to put anything in here ... its presense
// tells the firmware that we support multiple-sample
// realtime
command.Parameter = new byte[1];
}
public StartRealtimeMode(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
// don't need to put anything in here ... its presense
// tells the firmware that we support multiple-sample
// realtime
command.Parameter = new byte[1];
}
}
}

View File

@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Text;
using DTS.DASLib.Communication;
using DTS.DASLib.Utility;
namespace DTS.DASLib.Command.SLICE
{
public abstract class Commands_Stack_Utility: CommandBase
{
protected enum Commands
{
ArbitraryFlashWrite = 0x01,
ArbitraryFlashRead,
FlashSelfTest,
BusPowerControl,
ForceEnumeration,
GainSet,
GainQuery,
DACSet,
DACQuery,
SwitchSet,
SwitchQuery,
FilterSet,
FilterQuery,
};
protected Commands_Stack_Utility(ICommunication sock)
: base(sock)
{
this.command.Type = CommandPacket.CommandType.StackUtility;
}
protected Commands_Stack_Utility(ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
this.command.Type = CommandPacket.CommandType.StackUtility;
}
}
public class BusPowerControl: Commands_Stack_Utility
{
private bool _on;
public bool PowerOn
{
get { return _on; }
set
{
_on = value;
if(_on)
this.command.SetParameter(0, (byte)1);
else
this.command.SetParameter(0, (byte)0);
}
}
public BusPowerControl(ICommunication sock)
: base(sock)
{
this.command.Command = (byte)Commands.BusPowerControl;
this.command.Parameter = new byte[1];
PowerOn = false;
}
public BusPowerControl(ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
this.command.Command = (byte)Commands.BusPowerControl;
this.command.Parameter = new byte[1];
PowerOn = false;
}
public override string CommandToString()
{
var sb = new StringBuilder();
sb.AppendLine("Sending command BusPowerControl");
sb.AppendFormat("PowerOn: {0}", PowerOn);
sb.AppendLine();
return sb.ToString();
}
public override string ResponseToString()
{
var sb = new StringBuilder();
sb.AppendFormat("Response for command BusPowerControl: {0}", ResponseStatus);
sb.AppendLine();
sb.AppendFormat("PowerOn: {0}", PowerOn);
sb.AppendLine();
return sb.ToString();
}
}
public class ForceEnumeration: Commands_Stack_Utility
{
int _SLICECount;
public int SLICECount { get { return _SLICECount; } }
public ForceEnumeration(ICommunication sock)
: base(sock)
{
this.command.Command = (byte)Commands.ForceEnumeration;
this.command.Parameter = new byte[0];
_SLICECount = 0;
}
public ForceEnumeration(ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
this.command.Command = (byte)Commands.ForceEnumeration;
this.command.Parameter = new byte[0];
_SLICECount = 0;
}
protected override CommandReceiveAction WholePackage()
{
if(response.Status == CommandPacket.CommandStatus.StatusNoError)
{
byte b;
response.GetParameter(0, out b);
_SLICECount = (int)b;
}
return CommandReceiveAction.StopReceiving;
}
public override string CommandToString()
{
var sb = new StringBuilder();
sb.AppendLine("Sending command ForceEnumeration");
return sb.ToString();
}
public override string ResponseToString()
{
var sb = new StringBuilder();
sb.AppendFormat("Response for command ForceEnumeration: {0}", ResponseStatus);
sb.AppendLine();
sb.AppendFormat("SLICECount: {0}", SLICECount);
sb.AppendLine();
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
public class GetRealtimeSamplesTSRAIR : GetRealtimeSamples
{
public GetRealtimeSamplesTSRAIR(ICommunication sock)
: base(sock) { }
public GetRealtimeSamplesTSRAIR(ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec) { }
protected List<UInt64> _timestamps;
public List<UInt64> Timestamps => _timestamps;
protected override CommandReceiveAction WholePackage()
{
try
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
// Figure out the number of samples returned
int samples_returned = (response.ParameterLength - 8) / (_channels * 2);
_samplesReturned = samples_returned;
int data_bytes_returned = samples_returned * _channels * 2;
_data = new List<short[]>(_channels);
// Grab the sample number
if (response.ParameterLength > 0)
{
response.GetParameter(0, out _sampleNumber);
}
// Create the data arrays by channel
for (int i = 0; i < _channels; i++)
{
_data.Add(new short[samples_returned]);
}
// Grab the data
int parameter = 8;
for (int sample = 0; sample < samples_returned; sample++)
{
for (int channel = 0; channel < _channels; channel++)
{
response.GetParameter(parameter, out ushort uval);
//TSRAIR data is unsigned data. Convert sign, no need to normalize
_data[channel][sample] = (short)((((uval & 0x00FF) << 8) | ((uval >> 8) & 0x00FF)));
parameter += 2;
}
}
return CommandReceiveAction.StopReceiving;
}
}
catch
{
_samplesReturned = 0;
}
return CommandReceiveAction.StopReceiving;
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastGetDhcp : MulticastCommandBase
{
protected override Commands Command => Commands.GetDhcp;
private byte _dhcp;
public bool Dhcp => Convert.ToBoolean(_dhcp);
public MulticastGetDhcp(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public MulticastGetDhcp(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
base.WholePackage();
response.GetParameter(FIRST_PARAMETER_OFFSET, out _dhcp);
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {ResponseClientMac} " });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string> { $"MAC: {ResponseClientMac} Dhcp: {_dhcp}" });
}
}
}

View File

@@ -0,0 +1,328 @@
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Utilities.Logging;
using DTS.Common.Utils;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public abstract class MulticastCommandBase : CommandBase
{
protected const int IP_ADDR_SIZE = 16;
protected const int MAC_ADDR_SIZE = 18;
protected const int DOUBLE_MAC_ADDR_SIZE = 2 * MAC_ADDR_SIZE;
protected const int HOST_MAC_ADDRESS_OFFSET = 0;
protected const int CLIENT_MAC_ADDRESS_OFFSET = MAC_ADDR_SIZE;
protected const int FIRST_PARAMETER_OFFSET = CLIENT_MAC_ADDRESS_OFFSET + MAC_ADDR_SIZE;
protected const int DEFAULT_COMMAND_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE;
protected const int DEFAULT_RESPONSE_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE;
protected enum Commands
{
Reserved = 0x00,
AutoDiscover = 0x01,
SetIpAddress = 0x02,
GetIpAddress = 0x03,
SetSubnetAddress = 0x04,
GetSubnetAddress = 0x05,
SetGatewayAddress = 0x06,
GetGatewayAddress = 0x07,
SetDnsAddress = 0x08,
GetDnsAddress = 0x09,
SetDhcp = 0x0A,
GetDhcp = 0x0B,
ResetMcu = 0x0C,
WakeupBootloader = 0x0D,
Identify = 0x0E,
GetMACTable = 0x0F,
GetMACTable_Reserved = 0x10, // created in FW but not being used. Just ignore this command for now.
UdpQueryQTAS = 0x11, // query Arm-Trigger status via UDP multicast or unicast message via discovery route.
UdpAutoQATS = 0x12, // message command ID for auto-arm self-start UDP multicast QATS
UdpQATSInit = 0x13, // host command to send to DAS to start/stop UdpAutoQats message.
UdpAutoTiltSensorData = 0x14, //Periodic UDP response when enabled by cmd ID 0x13
UdpPrepareToShutdown = 0x15, //Command UUT to preserve auto-arm configuration and go to idle state ready for power down.
}
public enum Ports
{
Command = 8501,
Response = 8503,
}
public enum DeviceClasses
{
Unknown = 0,
Slice6 = 1 << 0,
SDB = 1 << 1,
ECM = 1 << 2,
S6DB = 1 << 3,
Slice6Air = 1 << 4,
PowerPro = 1 << 5,
TsrAir = 1 << 6,
S6DB3 = 1 << 7,
Any = 0xFFFF,
}
public enum ResponseOptions
{
AlwaysRespond = 0,
RespondIfNotBusy = 1,
RespondIfNotConnected = 2
}
public static int DEFAULT_RECEIVE_TIMEOUT_MS = 3000;
public const string DEFAULT_MULTICAST_ADDRESS = "239.1.2.3";
public const string DEFAULT_RECEIVE_ADDRESS = "239.4.5.6";
public static string MulticastAddress = DEFAULT_MULTICAST_ADDRESS;
public static string MulticastReceiveAddress = DEFAULT_RECEIVE_ADDRESS;
public static int CommandPort = (int)Ports.Command;
public static int ResponsePort = (int)Ports.Response;
protected abstract Commands Command { get; }
protected MulticastCommandBase(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.Multicast;
command.SetCommand((byte)Command, Command.ToString());
command.Parameter = new byte[DEFAULT_COMMAND_PAYLOAD_SIZE];
}
protected MulticastCommandBase(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Type = CommandPacket.CommandType.Multicast;
command.SetCommand((byte)Command, Command.ToString());
command.Parameter = new byte[DEFAULT_COMMAND_PAYLOAD_SIZE];
}
public void BuildPacket()
{
baseCommand.ComputeCRCs();
}
protected virtual bool StopAfterFirstMessage => true;
public int ReceiveTimeoutMs { get; set; } = DEFAULT_RECEIVE_TIMEOUT_MS;
private string _commandHostMac;
protected string CommandClientMac;
protected string ResponseHostMac;
protected string ResponseClientMac;
public string HostMac
{
get => _commandHostMac;
set { _commandHostMac = value; command.SetParameter(HOST_MAC_ADDRESS_OFFSET, _commandHostMac); }
}
public string ClientMac { set { CommandClientMac = value; command.SetParameter(CLIENT_MAC_ADDRESS_OFFSET, CommandClientMac); } }
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
response.GetParameter(HOST_MAC_ADDRESS_OFFSET, out ResponseHostMac);
response.GetParameter(CLIENT_MAC_ADDRESS_OFFSET, out ResponseClientMac);
if (!CommandClientMac.Equals(ResponseClientMac) || !HostMac.Equals(ResponseHostMac))
{
response.Status = DFConstantsAndEnums.CommandStatus.StatusInvalidPacket;
}
return CommandReceiveAction.StopReceiving;
}
public IPAddress BindToAdapterIPAddress { get; set; } = IPAddress.Any;
private void SendRequest()
{
var txGroupAddress = IPAddress.Parse(MulticastAddress);
var remoteEndPoint = new IPEndPoint(txGroupAddress, CommandPort);
UdpClient client = null;
if (BindToAdapterIPAddress == IPAddress.Any)
{
client = new UdpClient();
}
else
{
client = new UdpClient(new IPEndPoint(BindToAdapterIPAddress, CommandPort));
}
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.IpTimeToLive, 4);
command.SequenceNumber = 0;
command.ComputeCRCs();
var data = command.ToBytes();
client.Send(data, data.Length, remoteEndPoint);
client.Close();
}
/// <summary>
/// alternative to MulticastExecute,
/// just sends the multicast request, relies on
/// StartListening to have been called to process any incoming data
/// </summary>
public void SendCommand()
{
SendRequest();
}
/// <summary>
/// used to signal Listen() function that it should terminate
/// </summary>
protected ManualResetEvent _stopListening = new ManualResetEvent(false);
/// <summary>
/// starts a listening thread
/// </summary>
public void StartListening()
{
CancellationToken ct;
Task.Run(() => ReceiveThread(null, true, ct)).ConfigureAwait(false);
}
/// <summary>
/// stops any listening thread
/// </summary>
public void StopListening() => _stopListening.Set();
public void MulticastExecute(CancellationToken ct, bool waitForResponse = true)
{
if (ct.IsCancellationRequested) { return; }
//It's easier to kick off a worker thread to handle the receiver
using (var signalComplete = new ManualResetEvent(true))
{
if (true == waitForResponse)
{
signalComplete.Reset();
Task.Run(() => ReceiveThread(signalComplete, false, ct));
//Give it time to come up
Thread.Sleep(100);
}
//Send request once receive socket is set up
SendRequest();
WaitHandle.WaitAny(new[] { signalComplete, ct.WaitHandle });
}
}
protected virtual void ProcessResponse(byte[] data)
{
response = new CommandPacket(data);
WholePackage();
}
private const int UDP_ASYNC_RESPONSETIME_MS = 1000;
/// <summary>
/// Listens for UDP responses. Can signal when complete and can listen until _stopListening MRE is set.
/// </summary>
/// <param name="signalComplete">This MRE is set when the process is complete</param>
/// <param name="listenUntilStopped">This will cause the listening loop to continue untill stopped by the _stopListening MRE</param>
private void ReceiveThread(ManualResetEvent signalComplete, bool listenUntilStopped, CancellationToken ct)
{
var rxGroupAddress = IPAddress.Parse(MulticastReceiveAddress);
var endPoint = new IPEndPoint(BindToAdapterIPAddress, ResponsePort);
var receiver = new UdpClient();
receiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
receiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, ReceiveTimeoutMs);
_stopListening.Reset();
if (BindToAdapterIPAddress == IPAddress.Any) { receiver.ExclusiveAddressUse = false; }
try
{
receiver.Client.Bind(endPoint);
}
catch (Exception ex)
{
APILogger.Log(ex);
if (!ct.IsCancellationRequested)
{
signalComplete?.Set();
}
return;
}
if (ct.IsCancellationRequested) { return; }
try
{
if (BindToAdapterIPAddress == IPAddress.Any)
{
receiver.JoinMulticastGroup(rxGroupAddress);
}
else
{
receiver.JoinMulticastGroup(rxGroupAddress, BindToAdapterIPAddress);
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
var timeToWait = TimeSpan.FromMilliseconds(UDP_ASYNC_RESPONSETIME_MS);
byte[] data = new byte[0];
IAsyncResult asyncResult = null;
do
{
if (BindToAdapterIPAddress != IPAddress.Any && !NetworkUtils.IsNetworkInterfaceUp(BindToAdapterIPAddress))
{
Thread.Sleep(100);
continue;
}
asyncResult = receiver.BeginReceive(null, null);
asyncResult.AsyncWaitHandle.WaitOne(timeToWait);
if (asyncResult.IsCompleted)
{
try
{
IPEndPoint remoteEP = null;
data = receiver.EndReceive(asyncResult, ref remoteEP);
// EndReceive worked and we have received data and remote endpoint
System.Diagnostics.Debug.WriteLine("Got " + data.Length + " bytes from " + remoteEP);
ProcessResponse(data);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
} while (!_stopListening.WaitOne(0, false) && (asyncResult == null || asyncResult.IsCompleted) && !ct.IsCancellationRequested);
receiver.Close();
if (ct.IsCancellationRequested) { return; }
if (null != signalComplete && !signalComplete.WaitOne(0))
{
signalComplete.Set();
}
}
//This is a little hokey. It returns the first interface that's multicast compatible AND 'up'. It may not actually be the interface
//that we're interested in.
public static string GetMacAddress()
{
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var i in interfaces)
{
if (OperationalStatus.Up != i.OperationalStatus || !i.SupportsMulticast) continue;
var address = BitConverter.ToString(i.GetPhysicalAddress().GetAddressBytes());
address = address.Replace("-", ":");
return address;
}
return null;
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastGetIpAddress : MulticastCommandBase
{
protected override Commands Command => Commands.GetIpAddress;
private string _ip;
public string Ip => _ip;
public MulticastGetIpAddress(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public MulticastGetIpAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
base.WholePackage();
response.GetParameter(DOUBLE_MAC_ADDR_SIZE, out _ip);
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} " });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} IP: {_ip}" });
}
}
}

View File

@@ -0,0 +1,104 @@
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// this is ported from FirmwareTestUtility where it was written by Loc Pham. It is included for
/// 10573 implement SW side of single command/streaming download
/// </summary>
public class DownloadByteConverter
{
public enum DlByteIndex
{
Sync = 0,
Type = 1,
Command = 2,
Status = 3,
Group = 4,
Id = 5,
Datalength = 6,
SequenceNumber = 8,
HeaderCRC = 10,
DataCRC = 12,
DataADCStartOffset = 14,
DataADCEndOffset = 22,
DataStart = 30
}
public ushort SeqNumber { get; }
public ushort SeqNumberPrev { get; }
public ulong DlAdcStartOffset { get; }
public ulong DlAdcEndOffset { get; }
public ulong DlStreamSampleNumber { get; }
public ushort[] DlData { get; }
public uint[] DlChannels { get; }
public DownloadByteConverter(byte[] bytes)
{
SeqNumber = GetUShort(bytes, (int)DlByteIndex.SequenceNumber);
DlAdcStartOffset = GetUInt(bytes, (int)DlByteIndex.DataADCStartOffset);
DlAdcStartOffset = GetULong(bytes, (int)DlByteIndex.DataADCEndOffset);
DlData = new ushort[(bytes.Length - (int)DlByteIndex.DataStart) / 2];
if (SeqNumber == 0)
{
SeqNumberPrev = 0;
}
else
{
if (SeqNumberPrev != 0 &&
SeqNumberPrev != SeqNumber - 1)
{
System.Diagnostics.Debug.WriteLine("sequence out of order: ");
System.Diagnostics.Debug.WriteLine(SeqNumberPrev.ToString());
System.Diagnostics.Debug.WriteLine(SeqNumber.ToString());
}
}
SeqNumberPrev = SeqNumber;
for (var idx = 0; idx < DlData.Length; idx++)
{
DlData[idx] = GetDownloadUShort(bytes, (int)(DlByteIndex.DataStart + idx * 2));
}
}
private static ulong GetULong(byte[] bytes, int offset)
{
return (ulong)bytes[offset + 7] << 0 |
(ulong)bytes[offset + 6] << 8 |
(ulong)bytes[offset + 5] << 16 |
(ulong)bytes[offset + 4] << 24 |
(ulong)bytes[offset + 3] << 32 |
(ulong)bytes[offset + 2] << 40 |
(ulong)bytes[offset + 1] << 48 |
(ulong)bytes[offset + 0] << 56;
}
private static ushort GetUShort(byte[] bytes, int offset)
{
return (ushort)(bytes[offset + 1] |
bytes[offset + 0] << 8);
}
private static uint GetUInt(byte[] bytes, int offset)
{
return (uint)bytes[offset + 3] << 0 |
(uint)bytes[offset + 2] << 8 |
(uint)bytes[offset + 1] << 16 |
(uint)bytes[offset + 0] << 32;
}
/// <summary>
/// data apparently has a different byte order than parameters, so we have to
/// rearrange byte order for parameters but not data.
/// </summary>
/// <param name="bytes"></param>
/// <param name="offset"></param>
/// <returns></returns>
private static ushort GetDownloadUShort(byte[] bytes, int offset)
{
return (ushort)(bytes[offset + 0] | bytes[offset + 1] << 8);
}
}
}

View File

@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class QueryUARTEventData : EventDataCommands
{
public const int MAX_DATA_LENGTH = 2000;
public const int PAYLOAD_HEADER_LENGTH = 14;
protected override Commands Command => Commands.QueryUartEventData;
protected ushort _eventNumber;
protected uint _requestByteCount;
protected ulong _requestOffsetByteCount;
protected uint _payloadByteCount;
protected ulong _payloadOffsetByteCount;
protected byte[] _data;
public ushort EventNumber
{
get => _eventNumber;
set { _eventNumber = value; command.SetParameter(0, _eventNumber); }
}
public uint RequestByteCount
{
get => _requestByteCount;
set { _requestByteCount = value; command.SetParameter(2, _requestByteCount); }
}
public ulong RequestOffsetByteCount
{
get => _requestOffsetByteCount;
set { _requestOffsetByteCount = value; command.SetParameter(6, _requestOffsetByteCount); }
}
public uint PayloadByteCount => _payloadByteCount;
public ulong PayloadOffsetByteCount => _payloadOffsetByteCount;
public byte[] PayloadData => _data;
public QueryUARTEventData(ICommunication sock) : base(sock)
{
command.Parameter = new byte[14];
_data = null;
_eventNumber = 0;
_requestByteCount = 0;
_requestOffsetByteCount = 0;
_payloadByteCount = 0;
_payloadOffsetByteCount = 0;
command.ShouldLog = false;
}
public QueryUARTEventData(ICommunication sock, int timeoutMillisec) : base(sock, timeoutMillisec)
{
command.Parameter = new byte[14];
_data = null;
_eventNumber = 0;
_requestByteCount = 0;
_requestOffsetByteCount = 0;
_payloadByteCount = 0;
_payloadOffsetByteCount = 0;
command.ShouldLog = false;
}
public override void Execute(CommandCallback cb, object cbData)
{
// Do a little parameter checking
_data = null;
base.Execute(cb, cbData);
}
protected override CommandReceiveAction WholePackagePost()
{
// now send the data to the user
var stat = CommandStatus.Success;
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
var s = (int)response.Status;
APILogger.LogString("QueryUARTEventData.WholePackagePost: reporting failure, status==" + CommandPacketBase.StatusLabels[s] + " (0x" + s.ToString("X") + ")");
stat = CommandStatus.Failure;
}
var cbReport = new QueryEventDataReport(stat, UserCallbackData);
//cbReport.Data = new short[_channelsDownloaded][];
//for (var i = 0; i < _channelsDownloaded; i++)
// GetChannelData(i, out cbReport.Data[i]);
return UserCallback(cbReport);
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
return CommandReceiveAction.StopReceiving;
}
response.GetParameter(0, out ushort responseEventNum);
response.GetParameter(2, out _payloadByteCount);
response.GetParameter(6, out _payloadOffsetByteCount);
_data = new byte[_payloadByteCount];
for (var i = 0; i < _payloadByteCount; i++)
{
response.GetParameter(PAYLOAD_HEADER_LENGTH + i, out _data[i]);
}
return CommandReceiveAction.StopReceiving;
}
public override void SyncExecute()
{
// Do a little parameter checking
_data = null;
base.SyncExecute();
}
public override void CommandToString(ref List<List<string>> lines)
{
lines.Add(new List<string> { $"Event number: {EventNumber}, RequestByteCount: {RequestByteCount}, OffsetByteCount: {RequestOffsetByteCount}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
lines.Add(new List<string>
{
$"PayloadByteCount: {PayloadByteCount}, OffsetByteCount: {PayloadOffsetByteCount}"
});
}
public void LogResponse()
{
LogCommand(false);
}
}
}

View File

@@ -0,0 +1,290 @@
using System;
using System.Linq;
using DTS.Common.Constant;
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.SLICE.RealtimeCommands
{
/// <summary>
/// this "command" gets the next set of samples
/// note that in streaming mode no actual command is sent, we just pick up whatever data is in the RECV buffer
/// </summary>
public class RealtimeStreamingNextSamples : CommandBase, IGetRealtimeSamples
{
public RealtimeStreamingNextSamples(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
baseCommand = new CommandPacket();
}
public RealtimeStreamingNextSamples(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout)
: base(sock, msTimeout)
{
baseCommand = new CommandPacket();
}
public bool DigitalInput { get; set; }
public bool[] TransitionMode { get; set; }
/// <summary>
/// the realtime data sample data
/// </summary>
public RealtimeStreamDecoder RtData { get; private set; }
/// <summary>
/// these are both used in garbage packet detection
/// sample numbers are always increasing, sequence numbers are increasing but wrap around at ushort.max
/// we could just use only sample number and not sample number and sequence
/// for the garbage packet detection, but the number of samples per packet can be variable
/// (especially with different SPS and number of channels) while the sequence is always +1 increase
/// </summary>
private ulong _lastProcessedSampleNumber = ulong.MaxValue;
private ushort _lastSequenceNumber = 0;
/// <summary>
/// this is a fairly arbitrary choice, this is just used for garbage packet detection
/// in practical use we are unlikely to drop more than 50 sequence at 2k sps
/// so if we have more than a 1k difference there's a good chance the packet is garbage
/// </summary>
private const int MAX_SEQUENCE_DELTA = 1000;
public bool SignedData { get; set; } = false;
public void ProcessData()
{
try
{
#if REALTIME_LOGGING
var dt = DateTime.Now;
System.Diagnostics.Trace.WriteLine($"{dt.Hour}:{dt.Minute}:{dt.Second}.{dt.Millisecond} ProcessData");
#endif
RtData = null;
System.Threading.Thread.Sleep(20);
var bytes = baseResponse.ToBytes();
var headerCRC = response.HeaderCRC;
response.ComputeCRCs();
if (response.HeaderCRC != headerCRC)
{
//garbage packet, don't process
return;
}
if (!bytes.Any()) return;
RtData = new RealtimeStreamDecoder(bytes);
var bFailsSequenceCheck = false;
var sequenceDelta = Math.Abs(RtData.SequenceNumber - _lastSequenceNumber);
if (RtData.SequenceNumber != 0 && sequenceDelta > MAX_SEQUENCE_DELTA)
{
#if REALTIME_LOGGING
System.Diagnostics.Trace.WriteLine("garbage packet");
#endif
//crc matched, but we've still got a garbage packet, as determined by looking at the sequence #
bFailsSequenceCheck = true;
}
_lastSequenceNumber = RtData.SequenceNumber;
if (null == RtData || RtData.SampleNumber == _lastProcessedSampleNumber || bFailsSequenceCheck)
{
#if REALTIME_LOGGING
if (RtData.SampleNumber == _lastProcessedSampleNumber)
{
System.Diagnostics.Trace.WriteLine("Same packet #");
}
#endif
RtData = null;
return;
}
#if REALTIME_LOGGING
System.Diagnostics.Trace.WriteLine($"Processed: {RtData.SampleNumber}");
#endif
_lastProcessedSampleNumber = RtData.SampleNumber;
ChannelData = new short[Channels][];
for (var idx = 0; idx < Channels; idx++)
{
ChannelData[idx] = new short[SamplesReturned];
}
int insertPt;
short adc;
for (var i = 0; i < RtData.RtData.Length; i++)
{
//data is in the form of ABC where A is channel 0, and C is channel 2, so we can
//figure out the channel idx using modulo
var channelIdx = RtData.Channels[i % RtData.Channels.Length];
//per other realtime functions, we transform the ushort to a short
if (SignedData) { adc = (short)RtData.RtData[i]; }
else { adc = (short)(RtData.RtData[i] - 0x8000); }
//data is in the form of ABC, so what sample we are on from the first sample can be computed
//by dividing by the number of channels in the response
insertPt = Convert.ToInt32(Math.Floor((double)i / RtData.Channels.Length));
ChannelData[channelIdx][insertPt] = adc;
}
}
catch (Exception)
{
#if REALTIME_LOGGING
System.Diagnostics.Trace.WriteLine(ex.Message);
#endif
RtData = null;
}
}
/// <inheritdoc />
/// <summary>
/// the sample number of the first sample in the data stream
/// </summary>
public ulong SampleNumber => RtData.SampleNumber;
public ulong TimeStamp => RtData.TimeStamp;
public ulong SequenceNumber => RtData.SequenceNumber;
/// <summary>
/// All channel data for the DAS, note that if a channel is not in realtime
/// then it's short data values or not defined
/// this is all channels.
/// </summary>
private short[][] ChannelData { get; set; }
/// <inheritdoc />
/// <summary>
/// gets the sample data for a given channel index
/// </summary>
/// <param name="zeroBasedChannel"></param>
/// <returns></returns>
public short[] GetChannelData(int zeroBasedChannel)
{
return ChannelData[zeroBasedChannel];
}
/// <inheritdoc />
/// <summary>
/// this is the total number of channels on the DAS
/// this is used to build ChannelData
/// </summary>
public ushort Channels { get; set; }
/// <inheritdoc />
/// <summary>
/// count of how many samples have been performed
/// if data is ABCABCABC, then there are 3 samples returned
/// </summary>
public int SamplesReturned => RtData?.RtData.Length / RtData?.Channels.Length ?? 0;
/// <summary>
/// We need to override SyncExecute because we don't want to send anything. 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);
}
if (baseResponse.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
// didn't go well
var msg = MakeLogString("SyncExecute: response.Status = " + baseResponse.Status);
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);
APILogger.Log(ex);
}
// everything is fine, let it exit
if (LogCommands)
{
LogCommand(false);
}
break;
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveFailed:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
}
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveTimeout:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
}
case CommunicationConstantsAndEnums.CommunicationResult.SendFailed:
case CommunicationConstantsAndEnums.CommunicationResult.SendTimeout:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.SendFailed, msg);
}
default:
{
var msg = MakeLogString("SyncExecute: Unknown ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new Exception(msg);
}
}
}
finally
{
recorder.ExecuteIsBusy = false;
ProcessData();
}
}
}
}

View File

@@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
/// <summary>
/// this class was ported from FWTU RealtimeCommands, it appears almost verbatim to there
/// </summary>
public class UDPRealtimeByteConverter
{
public enum UDP_BYTE_INDEX
{
PKT_PATTERN = 0, // u16
CHANNEL_ID = 2, // u16
PKT_LEN = 4, // u32
DATA_LEN = 8, // u32
DATA_TYPE_VER = 12, // u8
SEQ_NUMBER = 13, // u8
PKT_FLAGS = 14, // u8
DATA_TYPE = 15, // u8
REL_TIME32 = 16, // u32 of 48
REL_TIME16 = 20, // u16
HDR_CRC16 = 22, // u16
PTP_U32_LSW = 24, // u32
PTP_U32_MSW = 28, // u32
RSV_U16 = 32, // u32
HDR2CRC16 = 34, // u16
CSDW = 36, // u32
DATA_START = 40, // data start address
}
// This is list of data type for UDP to support
public enum UDP_DATA_TYPE
{
// 0x21 for analog format 1. 0x01 = CGDP format 1 (setup record). 0x12 = Time Data, Format 2 (PTP time)
CGDP_TYPE = 0x01, // Setup XML record. 1. Setup Record, periodic message sent out.
TIME_DATA_PTP = 0x12, // Time data, format 2. Periodic message.
ANALOG_DATA_FORMAT_1 = 0x21, // Analog data format 3. Periodic message.
}
public ushort PacketPattern { get; private set; }
public ushort DataChannelID { get; private set; }
public uint PacketLength { get; private set; }
/// <summary>
/// careful if you use this, it's not the same as
/// RtData.Length ...
/// </summary>
public uint DataLength { get; private set; }
public byte DataTypeVersion { get; private set; }
public byte SequenceNumber { get; private set; }
public byte PacketFlags { get; private set; }
public byte DataType { get; private set; }
public uint RelativeTime32 { get; private set; }
public ushort RelativeTime16 { get; private set; }
public ushort HdrCrc16 { get; private set; }
public uint PtpTimeStampSec { get; private set; }
public uint PtpTimeStampNsec { get; private set; }
public uint Hdr2Crc16 { get; private set; }
public uint ChannelMask { get; private set; }
public ulong UdpSampleCount { get; private set; }
public ushort[] RtData { get; private set; }
public uint[] Channels { get; private set; }
public byte SequenceNumberPrev { get; private set; }
public UDPRealtimeByteConverter(byte[] bytes)
{
// TBD: Currently expect 36byte header. If simplified version with 24Byte,
// we have to account for the right offset. RTC will be used then.
PacketPattern = GetUShort(bytes, (int)UDP_BYTE_INDEX.PKT_PATTERN);
DataChannelID = GetUShort(bytes, (int)UDP_BYTE_INDEX.CHANNEL_ID);
PacketLength = GetUInt(bytes, (int)UDP_BYTE_INDEX.PKT_LEN);
DataLength = GetUInt(bytes, (int)UDP_BYTE_INDEX.DATA_LEN);
DataTypeVersion = GetByte(bytes, (int)UDP_BYTE_INDEX.DATA_TYPE_VER);
SequenceNumber = GetByte(bytes, (int)UDP_BYTE_INDEX.SEQ_NUMBER);
PacketFlags = GetByte(bytes, (int)UDP_BYTE_INDEX.PKT_FLAGS);
DataType = GetByte(bytes, (int)UDP_BYTE_INDEX.DATA_TYPE); // 0x21 for analog format 1. 0x01 = CGDP format 1 (setup record). 0x12 = Time Data, Format 2 (PTP time)
RelativeTime32 = GetUInt(bytes, (int)UDP_BYTE_INDEX.REL_TIME32);
RelativeTime16 = GetUShort(bytes, (int)UDP_BYTE_INDEX.REL_TIME16);
HdrCrc16 = GetUShort(bytes, (int)UDP_BYTE_INDEX.HDR_CRC16);
PtpTimeStampSec = GetUInt(bytes, (int)UDP_BYTE_INDEX.PTP_U32_MSW);
PtpTimeStampNsec = GetUInt(bytes, (int)UDP_BYTE_INDEX.PTP_U32_LSW);
Hdr2Crc16 = GetUShort(bytes, (int)UDP_BYTE_INDEX.HDR2CRC16);
if (DataType == (int)UDP_DATA_TYPE.ANALOG_DATA_FORMAT_1)
{
RtData = new ushort[(DataLength - 4) / 2]; // ushort[(bytes.Length - (int)UDP_BYTE_INDEX.DATA_START) / 2];
var mychannels = new List<uint>();
for (var i = 0; i < 6; i++) // var length = dataLength;
{
//if (ba.Get(i)) assume all 6 channels if UDP.
{
mychannels.Add(Convert.ToUInt32(i));
}
}
Channels = mychannels.ToArray();
UdpSampleCount = Convert.ToUInt64(RtData.Length / Channels.Length);
SequenceNumberPrev = SequenceNumber;
// TBD: check for pktFlag if the optional 2nd header is being used or not. If not,
// we can start the data from UDP_BYTE_INDEX.PTP_U32_LSW
for (var idx = 0; idx < RtData.Length; idx++)
{
RtData[idx] = GetRTUShort(bytes, (int)(UDP_BYTE_INDEX.DATA_START + idx * 2));
RtData[idx] ^= 0x8000;
}
}
else
{
// TBD for other packet types.
RtData = null;
}
}
private static ulong GetULong(byte[] bytes, int offset)
{
return (ulong)bytes[offset + 7] << 0 |
(ulong)bytes[offset + 6] << 8 |
(ulong)bytes[offset + 5] << 16 |
(ulong)bytes[offset + 4] << 24 |
(ulong)bytes[offset + 3] << 32 |
(ulong)bytes[offset + 2] << 40 |
(ulong)bytes[offset + 1] << 48 |
(ulong)bytes[offset + 0] << 56;
}
private static ushort GetUShort(byte[] bytes, int offset)
{
return (ushort)(bytes[offset + 1] |
bytes[offset + 0] << 8);
}
private static byte GetByte(byte[] bytes, int offset)
{
return bytes[offset];
}
private static uint GetUInt(byte[] bytes, int offset)
{
return (uint)bytes[offset + 3] << 0 |
(uint)bytes[offset + 2] << 8 |
(uint)bytes[offset + 1] << 16 |
(uint)bytes[offset + 0] << 24;
}
/// <summary>
/// data apparently has a different byte order than parameters, so we have to
/// rearrange byte order for parameters but not data.
/// </summary>
/// <param name="bytes"></param>
/// <param name="offset"></param>
/// <returns></returns>
private static ushort GetRTUShort(byte[] bytes, int offset)
{
return (ushort)(bytes[offset + 0] |
bytes[offset + 1] << 8);
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Reflection;
using System.IO;
using System.Diagnostics;
using DTS.Common.ICommunication;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Command.SLICE
{
public abstract class CommandBase : SliceCommandBase
{
public CommandBase(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock)
{
command = new CommandPacket();
}
public CommandBase(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec)
{
command = new CommandPacket();
}
protected override CommandPacketBase GetCommandPacket()
{
return new CommandPacket();
}
protected override CommandPacketBase GetCommandPacket(byte[] buffer)
{
return new CommandPacket(buffer);
}
}
}

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MACTableEntry" Collapsed="true">
<Position X="8.25" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAABAAAAAAAAAAAEAAAAAACBAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MACTableEntry.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.DiscoveredConnectedSlice" Collapsed="true">
<Position X="6.5" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAACAAAAAAA=</HashCode>
<FileName>MulticastCommands\MACTableEntry.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastAutoDiscover" Collapsed="true">
<Position X="14" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>EAAACUEAAAIAIAgIAEBAFABACAgRgAACQCQACWAAABA=</HashCode>
<FileName>MulticastCommands\MulticastAutoDiscover.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastCommandBase" Collapsed="true">
<Position X="15.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>IAACgAAJEABAAAAAIIAEBggQwAAAwCAAFAEIgsgQAAA=</HashCode>
<FileName>MulticastCommands\MulticastCommandBase.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastDiscoverSlice6" Collapsed="true">
<Position X="25.25" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>QAIACQAAACMKAAAAABAABARAAAgTiAAAQAAQIWAAQEA=</HashCode>
<FileName>MulticastCommands\MulticastDiscoverSlice6.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastGetDhcp" Collapsed="true">
<Position X="0.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAAABABAAAAAAAAAAAAAAEAAAEA=</HashCode>
<FileName>MulticastCommands\MulticastGetDhcp.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastGetDnsAddress" Collapsed="true">
<Position X="7.25" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEAAAAAAAAAAAAAAEAABABAAAAAAAAAAAAAAEAAAEA=</HashCode>
<FileName>MulticastCommands\MulticastGetDnsAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastGetGatewayAddress" Collapsed="true">
<Position X="16.25" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAACAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAEAAAEA=</HashCode>
<FileName>MulticastCommands\MulticastGetGatewayAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastGetIpAddress" Collapsed="true">
<Position X="20.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAABABABAAAAAAAAAAAAAAEAAIEA=</HashCode>
<FileName>MulticastCommands\MulticastGetIpAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastGetSubnetAddress" Collapsed="true">
<Position X="27.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABABAAAAAAACAAAAAAEAAAFA=</HashCode>
<FileName>MulticastCommands\MulticastGetSubnetAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastIdentify" Collapsed="true">
<Position X="2.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABABAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MulticastIdentify.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastResetMcu" Collapsed="true">
<Position X="9.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABABAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MulticastResetMcu.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastSetDhcp" Collapsed="true">
<Position X="18.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAAABABAAAAAAAAAQAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MulticastSetDhcp.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastSetDnsAddress" Collapsed="true">
<Position X="23" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEAAAAAAAAAAAAAAEAABABAAAAAAAAAQAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MulticastSetDnsAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastSetGatewayAddress" Collapsed="true">
<Position X="29.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAACAAAAAAAAAAAAAAAJABAAAAAAAAAQAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MulticastSetGatewayAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastSetIpAddress" Collapsed="true">
<Position X="5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAABABABAAAAAAAAAQAAAAAAAIAA=</HashCode>
<FileName>MulticastCommands\MulticastSetIPAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastSetSubnetAddress" Collapsed="true">
<Position X="11.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABABAAAAAAACAQAAAAAAAABA=</HashCode>
<FileName>MulticastCommands\MulticastSetSubnetAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,71 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
using DTS.Common.Utilities;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
public class RetrieveSingleSample : RealtimeCommandBase
{
protected override Commands _Command => Commands.RetrieveSingleSample;
public short[] _data;
public short GetChannelData(int zeroBasedChannel)
{
return _data[zeroBasedChannel];
}
public ushort Channels
{
get
{
if (null == _data) return 0;
return (ushort)_data.Length;
}
}
public RetrieveSingleSample(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public RetrieveSingleSample(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
try
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
// Figure out the number of samples returned
var unsignedData = new ushort[response.Parameter.Length / 2];
_data = new short[response.Parameter.Length / 2];
for (var i = 0; i < response.Parameter.Length / 2; i++)
{
response.GetParameter(2 * i, out unsignedData[i]);
if (unsignedData[i] > 32768)
{
_data[i] = (short)(unsignedData[i] - 65536);
}
else
{
_data[i] = (short)unsignedData[i];
}
}
return CommandReceiveAction.StopReceiving;
}
}
catch { }
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string> { $"Channels: {Channels}, Data: {ArrayToString.ArrayObjectToString(_data)}" });
}
}
}

View File

@@ -0,0 +1,167 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D015F93D-9507-4484-977B-4CF1BDC0B30E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DTS.DASLib.Command.SLICE</RootNamespace>
<AssemblyName>SLICECommands</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkProfile />
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ArmCommands.cs" />
<Compile Include="DownloadCommands\DownloadByteConverter.cs" />
<Compile Include="DownloadCommands\EventDataCommands.cs" />
<Compile Include="DownloadCommands\GetNextDownloadStreamDataSamples.cs" />
<Compile Include="DownloadCommands\QueryEventDataBase.cs" />
<Compile Include="DownloadCommands\QueryEventDataReport.cs" />
<Compile Include="DownloadCommands\QueryTotalEventCount.cs" />
<Compile Include="DownloadCommands\QueryEthernetEventData.cs" />
<Compile Include="DownloadCommands\QueryUARTEventData.cs" />
<Compile Include="DownloadCommands\QueryEthernetEventInfo.cs" />
<Compile Include="DownloadCommands\QueryUARTEventInfo.cs" />
<Compile Include="DownloadCommands\ResetEventList.cs" />
<Compile Include="DownloadCommands\StartDownloadStreamData.cs" />
<Compile Include="MulticastCommands\MACTableEntry.cs" />
<Compile Include="MulticastCommands\MulticastAutoDiscover.cs" />
<Compile Include="MulticastCommands\MulticastCommandBase.cs" />
<Compile Include="MulticastCommands\MulticastDiscoverSlice6.cs" />
<Compile Include="MulticastCommands\MulticastGetDhcp.cs" />
<Compile Include="MulticastCommands\MulticastGetDnsAddress.cs" />
<Compile Include="MulticastCommands\MulticastGetGatewayAddress.cs" />
<Compile Include="MulticastCommands\MulticastGetIpAddress.cs" />
<Compile Include="MulticastCommands\MulticastGetSubnetAddress.cs" />
<Compile Include="MulticastCommands\MulticastIdentify.cs" />
<Compile Include="MulticastCommands\MulticastResetMcu.cs" />
<Compile Include="MulticastCommands\MulticastSetDhcp.cs" />
<Compile Include="MulticastCommands\MulticastSetDnsAddress.cs" />
<Compile Include="MulticastCommands\MulticastSetGatewayAddress.cs" />
<Compile Include="MulticastCommands\MulticastSetIPAddress.cs" />
<Compile Include="MulticastCommands\MulticastSetSubnetAddress.cs" />
<Compile Include="MulticastCommands\MulticastUDPQueryQATS.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="AttributeCommands.cs" />
<Compile Include="CalibrationCommands.cs" />
<Compile Include="CommandBase.cs" />
<Compile Include="CommandPacket.cs" />
<Compile Include="FirmwareUpdateCommands.cs" />
<Compile Include="InformationCommands.cs" />
<Compile Include="Ptp1588Commands.cs" />
<Compile Include="QAandUtilityCommands.cs" />
<Compile Include="RealtimeCommands\EndRealtimeMode.cs" />
<Compile Include="RealtimeCommands\GetRealtimeSamples.cs" />
<Compile Include="RealtimeCommands\GetRealtimeSamplesSLICE2.cs" />
<Compile Include="RealtimeCommands\GetRealtimeSamplesSLICE6.cs" />
<Compile Include="RealtimeCommands\GetRealtimeSamplesTSRAIR.cs" />
<Compile Include="RealtimeCommands\IGetRealtimeSamples.cs" />
<Compile Include="RealtimeCommands\RealtimeCommandBase.cs" />
<Compile Include="RealtimeCommands\RealtimeStreamDecoder.cs" />
<Compile Include="RealtimeCommands\RealtimeStreamingNextSamples.cs" />
<Compile Include="RealtimeCommands\RetrieveSampleAverage.cs" />
<Compile Include="RealtimeCommands\RetrieveSingleSample.cs" />
<Compile Include="RealtimeCommands\StartRealtimeMode.cs" />
<Compile Include="RealtimeCommands\StartRealtimeStreamingMode.cs" />
<Compile Include="RealtimeCommands\StreamConfigUDP.cs" />
<Compile Include="RealtimeCommands\StreamReaderUDP.cs" />
<Compile Include="RealtimeCommands\UDPRealtimeByteConverter.cs" />
<Compile Include="RealtimeCommands\UDPStreamPacket.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\DTS.Common.DASResource\DTS.Common.DASResource.csproj">
<Project>{f621ce48-bb4b-4cfc-a325-9410b721cc44}</Project>
<Name>DTS.Common.DASResource</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\DTS.Common.ICommunication\DTS.Common.ICommunication.csproj">
<Project>{f57b954e-a49a-4110-b36c-b5abab3e230b}</Project>
<Name>DTS.Common.ICommunication</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
<Project>{d6da1b74-c711-43c2-91b1-1908a8d04dbf}</Project>
<Name>DTS.Common.Utilities</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\DTS.Common\DTS.Common.csproj">
<Project>{f7a0804f-61a4-40ae-83d0-f1137622b592}</Project>
<Name>DTS.Common</Name>
</ProjectReference>
<ProjectReference Include="..\ICommand\ICommand.csproj">
<Project>{58e70872-8acc-4957-bb8e-d3746bcc536d}</Project>
<Name>ICommand</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Design\ClassDiagram_DownloadCommands.cd" />
<None Include="Design\ClassDiagram_MulticastCommands.cd" />
<None Include="Design\ClassDiagram_RealTimeCommands.cd" />
<None Include="Design\ClassDiagram_SliceCommands.cd" />
<None Include="Properties\DataSources\AttributeTypes.SystemAttributes_Bridge.datasource" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,289 @@
using System;
using System.Linq;
using DTS.Common.Constant;
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.SLICE.RealtimeCommands
{
/// <summary>
/// this "command" gets the next set of samples
/// note that in streaming mode no actual command is sent, we just pick up whatever data is in the RECV buffer
/// </summary>
public class RealtimeStreamingNextSamples : CommandBase, IGetRealtimeSamples
{
public RealtimeStreamingNextSamples(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
baseCommand = new CommandPacket();
}
public RealtimeStreamingNextSamples(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout)
: base(sock, msTimeout)
{
baseCommand = new CommandPacket();
}
public bool DigitalInput { get; set; }
public bool[] TransitionMode { get; set; }
/// <summary>
/// the realtime data sample data
/// </summary>
public RealtimeStreamDecoder RtData { get; private set; }
/// <summary>
/// these are both used in garbage packet detection
/// sample numbers are always increasing, sequence numbers are increasing but wrap around at ushort.max
/// we could just use only sample number and not sample number and sequence
/// for the garbage packet detection, but the number of samples per packet can be variable
/// (especially with different SPS and number of channels) while the sequence is always +1 increase
/// </summary>
private ulong _lastProcessedSampleNumber = ulong.MaxValue;
private ushort _lastSequenceNumber = 0;
/// <summary>
/// this is a fairly arbitrary choice, this is just used for garbage packet detection
/// in practical use we are unlikely to drop more than 50 sequence at 2k sps
/// so if we have more than a 1k difference there's a good chance the packet is garbage
/// </summary>
private const int MAX_SEQUENCE_DELTA = 1000;
public void ProcessData()
{
try
{
#if REALTIME_LOGGING
var dt = DateTime.Now;
System.Diagnostics.Trace.WriteLine($"{dt.Hour}:{dt.Minute}:{dt.Second}.{dt.Millisecond} ProcessData");
#endif
RtData = null;
System.Threading.Thread.Sleep(20);
var bytes = baseResponse.ToBytes();
var headerCRC = response.HeaderCRC;
response.ComputeCRCs();
if (response.HeaderCRC != headerCRC)
{
//garbage packet, don't process
return;
}
if (!bytes.Any()) return;
RtData = new RealtimeStreamDecoder(bytes);
var bFailsSequenceCheck = false;
var sequenceDelta = Math.Abs(RtData.SequenceNumber - _lastSequenceNumber);
if (RtData.SequenceNumber != 0 && sequenceDelta > MAX_SEQUENCE_DELTA)
{
#if REALTIME_LOGGING
System.Diagnostics.Trace.WriteLine("garbage packet");
#endif
//crc matched, but we've still got a garbage packet, as determined by looking at the sequence #
bFailsSequenceCheck = true;
}
_lastSequenceNumber = RtData.SequenceNumber;
if (null == RtData || RtData.SampleNumber == _lastProcessedSampleNumber || bFailsSequenceCheck)
{
#if REALTIME_LOGGING
if (RtData.SampleNumber == _lastProcessedSampleNumber)
{
System.Diagnostics.Trace.WriteLine("Same packet #");
}
#endif
RtData = null;
return;
}
#if REALTIME_LOGGING
System.Diagnostics.Trace.WriteLine($"Processed: {RtData.SampleNumber}");
#endif
_lastProcessedSampleNumber = RtData.SampleNumber;
ChannelData = new short[Channels][];
for (var idx = 0; idx < Channels; idx++)
{
ChannelData[idx] = new short[SamplesReturned];
}
int insertPt;
short adc;
for (var i = 0; i < RtData.RtData.Length; i++)
{
//data is in the form of ABC where A is channel 0, and C is channel 2, so we can
//figure out the channel idx using modulo
var channelIdx = RtData.Channels[i % RtData.Channels.Length];
//per other realtime functions, we transform the ushort to a short
adc = (short)(RtData.RtData[i] - 0x8000);
//data is in the form of ABC, so what sample we are on from the first sample can be computed
//by dividing by the number of channels in the response
insertPt = Convert.ToInt32(Math.Floor((double)i / RtData.Channels.Length));
ChannelData[channelIdx][insertPt] = adc;
}
}
catch (Exception)
{
#if REALTIME_LOGGING
System.Diagnostics.Trace.WriteLine(ex.Message);
#endif
RtData = null;
}
}
/// <inheritdoc />
/// <summary>
/// the sample number of the first sample in the data stream
/// </summary>
public ulong SampleNumber => RtData.SampleNumber;
public ulong TimeStamp => RtData.TimeStamp;
public ulong SequenceNumber => RtData.SequenceNumber;
/// <summary>
/// All channel data for the DAS, note that if a channel is not in realtime
/// then it's short data values or not defined
/// this is all channels.
/// </summary>
private short[][] ChannelData { get; set; }
/// <inheritdoc />
/// <summary>
/// gets the sample data for a given channel index
/// </summary>
/// <param name="zeroBasedChannel"></param>
/// <returns></returns>
public short[] GetChannelData(int zeroBasedChannel)
{
return ChannelData[zeroBasedChannel];
}
/// <inheritdoc />
/// <summary>
/// this is the total number of channels on the DAS
/// this is used to build ChannelData
/// </summary>
public ushort Channels { get; set; }
/// <inheritdoc />
/// <summary>
/// count of how many samples have been performed
/// if data is ABCABCABC, then there are 3 samples returned
/// </summary>
public int SamplesReturned => RtData?.RtData.Length / RtData?.Channels.Length ?? 0;
/// <summary>
/// We need to override SyncExecute because we don't want to send anything. 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);
}
if (baseResponse.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
// didn't go well
var msg = MakeLogString("SyncExecute: response.Status = " + baseResponse.Status);
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);
APILogger.Log(ex);
}
// everything is fine, let it exit
if (LogCommands)
{
LogCommand(false);
}
break;
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveFailed:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
}
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveTimeout:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
}
case CommunicationConstantsAndEnums.CommunicationResult.SendFailed:
case CommunicationConstantsAndEnums.CommunicationResult.SendTimeout:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.SendFailed, msg);
}
default:
{
var msg = MakeLogString("SyncExecute: Unknown ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new Exception(msg);
}
}
}
finally
{
recorder.ExecuteIsBusy = false;
ProcessData();
}
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastSetSubnetAddress : MulticastCommandBase
{
private const int COMMAND_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE + IP_ADDR_SIZE;
protected override Commands Command => Commands.SetSubnetAddress;
private string _subnet;
public string Subnet { set { _subnet = value; command.SetParameter(FIRST_PARAMETER_OFFSET, _subnet); } }
public MulticastSetSubnetAddress(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public MulticastSetSubnetAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} Subnet: {_subnet}" });
}
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastResetMcu : MulticastCommandBase
{
protected override Commands Command => Commands.ResetMcu;
public MulticastResetMcu(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public MulticastResetMcu(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac}" });
}
}
}

View File

@@ -0,0 +1,83 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
using DTS.Common.Utilities;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
public class RetrieveSampleAverage : RealtimeCommandBase
{
protected override Commands _Command => Commands.RetrieveSampleAverage;
const int SAMPLES_POSITION = 0;
const int DATA_POSITION = 2;
private ushort _samples;
public ushort Samples
{
set { _samples = value; command.SetParameter(SAMPLES_POSITION, _samples); }
get => _samples;
}
public short[] _data;
public short GetChannelData(int zeroBasedChannel)
{
return _data[zeroBasedChannel];
}
public ushort Channels
{
get
{
if (null == _data) return 0;
return (ushort)_data.Length;
}
}
public RetrieveSampleAverage(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[DATA_POSITION];
}
public RetrieveSampleAverage(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Parameter = new byte[DATA_POSITION];
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
// Figure out how many samples were actually used to compute the means --
// we may have requested more than the recorder has RAM to store
response.GetParameter(SAMPLES_POSITION, out _samples);
// Figure out the number of channels returned and grab the means
var numChannels = (response.Parameter.Length - 2) / 2;
_data = new short[numChannels];
for (var i = 0; i < numChannels; i++)
{
response.GetParameter(2 * i + DATA_POSITION, out _data[i]);
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"Samples Requested: {Samples}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>
{
$"Channels: {Channels}, Samples Used: {Samples}, Data: {ArrayToString.ArrayObjectToString(_data)}"
});
}
}
}

View File

@@ -0,0 +1,199 @@
using DTS.Common.Utilities.Logging;
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using DTS.Common.Enums;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
/// <summary>
/// this class was ported from FWTU
/// </summary>
public class StreamReaderUDP
{
public string StreamAddress { get; }
/// <summary>
/// appears to be the parameters (line) sent to the start command
/// </summary>
public byte[] cmdline { get; set; }
private Socket _udpSocket { get; set; }
/// <summary>
/// IP of our receive endpoint. Either 0.0.0.0 or a specified adapter's IP
/// FB15531: Follow pattern for multicast AutoDiscovery in StreamReader
/// </summary>
public string HostIPAddress { get; set; } = IPAddress.Any.ToString();
public void CloseSocket()
{
try
{
_udpSocket.Close();
}
catch (Exception e)
{
APILogger.LogException(e);
}
}
public UDPStreamProfile UDPStreamType
{
get;
set;
}
private EndPoint _uDPEndpoint;
public EndPoint UDPEndpoint
{
get => _uDPEndpoint;
set => _uDPEndpoint = value;
}
public ulong UDPSampleNumber { get; set; }
public StreamReaderUDP(string streamAddress, string hostAddress, UDPStreamProfile uDPStreamType, byte[] channels)
{
StreamAddress = streamAddress.TrimEnd('/');
UDPSampleNumber = 0;
UDPStreamType = uDPStreamType;
Channels = channels;
HostIPAddress = hostAddress;
Configure();
}
public byte[] Channels { get; set; } = new byte[0];
private void Configure()
{
// setup parameter for command
var channelMaskAndReserved = 0; // default to all channels.
//I'm not sure this is supported yet...
//if (Channels.Any())
//{
// foreach (var ch in Channels)
// {
// channelMaskAndReserved |= 1 << ch;
// }
//}
var channelList = BitConverter.GetBytes(channelMaskAndReserved);
// create parameter for streaming command.
cmdline = new byte[4 + StreamAddress.Length];
var paramNetAddr = Encoding.ASCII.GetBytes(StreamAddress);
Buffer.BlockCopy(channelList, 0, cmdline, 0, channelList.Length);
Buffer.BlockCopy(paramNetAddr, 0, cmdline, channelList.Length,
paramNetAddr
.Length); // System.Buffer.BlockCopy(netAddr.ToArray(), 0, cmdline, channelList.Length, netAddr.Length);
// get IP and port udp://239.1.2.10:portID
var parts = StreamAddress.Split(':');
if (parts.Length != 3)
{
throw new Exception($"Invalid UDP address:{StreamAddress}");
}
// remove '//' or '/' from IP and port
var udphost = parts[1].Trim('/');
var udpport = parts[2].Trim('/');
_udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
var iep = IPAddress.TryParse(HostIPAddress, out var address) ? new IPEndPoint(address, Convert.ToUInt16(udpport)) : new IPEndPoint(IPAddress.Any, Convert.ToUInt16(udpport));
UDPEndpoint = iep;
try
{
_udpSocket.Bind(iep);
}
catch (Exception e)
{
APILogger.LogException(e);
_udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 2000);
_udpSocket.Bind(iep); // retry again.
}
// check for udp broadcast
var ipChecks = udphost.Split('.');
var ipV4Check = Convert.ToInt32(ipChecks[0]);
if ((ipV4Check >= 224) & (ipV4Check <= 239))
{
var mcastOption = new MulticastOption(IPAddress.Parse(udphost));
if (iep.Address != IPAddress.Any)
{
mcastOption = new MulticastOption(IPAddress.Parse(udphost), iep.Address);
}
_udpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption); // "239.1.2.10")));
}
//set timer for recv_socket
_udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 2000);
}
/// <summary>
/// receives any packets waiting
/// returns null if no information is ready, otherwise a structure filled with information
/// </summary>
/// <returns></returns>
public UDPStreamPacket Read()
{
//receive data
var databuf = new byte[2000];
var recv = _udpSocket.ReceiveFrom(databuf, ref _uDPEndpoint);
if (recv <= 0)
{
return null;
}
var data = new byte[recv];
Buffer.BlockCopy(databuf, 0, data, 0, recv);
var udpData = new UDPRealtimeByteConverter(data);
var udpStreamPacket = new UDPStreamPacket();
udpStreamPacket.ChannelData = new short[Channels.Length][];
//fun fact, sending all channels right now, so regardless of how many were configured to send, use this
var numChannels = 6;
//calculate how many samples are in the packet, but use the floor incase it's not complete
var numSamples = Convert.ToUInt64(Math.Floor((double)udpData.RtData.Length / numChannels));
for (var i = 0; i < Channels.Length; i++)
{
udpStreamPacket.ChannelData[i] = new short[numSamples];
}
//forward declarations to reduce a little churn
byte channel = 0;
var list = Channels.ToList();
var sampleIndex = 0UL;
short adc = 0;
for (var i = 0; i < udpData.RtData.Length; i++)
{
//which channel this sample is for
channel = Convert.ToByte(i % numChannels);
//which channel in the list this is for
var channelIdx = list.IndexOf(channel);
//channel is not in list, don't care about this sample
if (channelIdx < 0) { continue; }
//which sample in a sequence of multiple samples this is
sampleIndex = Convert.ToUInt64(Math.Floor((double)i / numChannels));
//we should have all complete packets, but if there's an incomplete round
//this will skip it
if (sampleIndex >= numSamples) { continue; }
//add the sample into the list of samples
adc = (short)udpData.RtData[i];
udpStreamPacket.ChannelData[channelIdx][sampleIndex] = adc;
}
udpStreamPacket.PTPTimesec = Convert.ToUInt32(udpData.PtpTimeStampSec);
udpStreamPacket.PTPTimeNsec = Convert.ToUInt32(udpData.PtpTimeStampNsec);
udpStreamPacket.PTPSyncStatusError = Convert.ToBoolean(udpData.PacketFlags & 0x20);
udpStreamPacket.ADCOverflowStatus = Convert.ToBoolean(udpData.PacketFlags & 0x10);
udpStreamPacket.TimeStamp = 0L;
//packet does not contain a sample number, so we calculate it
udpStreamPacket.SampleNumber = udpData.SequenceNumber * numSamples;
return udpStreamPacket;
}
}
}

View File

@@ -0,0 +1,64 @@
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// this was ported almost directly from FirmwareTestUtility, where it was written by Loc Pham
/// this was done for
/// 10573 implement SW side of single command/streaming download
/// this command should put SLICE2 firmware >= A1N4 into download streaming mode
/// any command should be sufficient to stop this streaming early
/// </summary>
public class StartDownloadStreamData : EventDataCommands
{
protected override Commands Command => Commands.StartDownloadStreamData;
public StartDownloadStreamData(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[18];
}
public StartDownloadStreamData(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Parameter = new byte[18];
}
public const byte AllChannels = 0xFF;
private ushort _eventNumber;
private ulong _firstSample;
private ulong _lastSample;
public ushort EventNumber
{
get => _eventNumber;
set
{
_eventNumber = value;
command.SetParameter(0, _eventNumber);
}
}
public virtual ulong FirstSample
{
get => _firstSample;
set
{
_firstSample = value;
command.SetParameter(2, _firstSample);
}
}
public virtual ulong LastSample
{
get => _lastSample;
set
{
_lastSample = value;
command.SetParameter(10, _lastSample);
}
}
}
}

View File

@@ -0,0 +1,19 @@
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
public class EndRealtimeMode : RealtimeCommandBase
{
protected override Commands _Command => Commands.EndRealtimeMode;
public EndRealtimeMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public EndRealtimeMode(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastGetGatewayAddress : MulticastCommandBase
{
protected override Commands Command => Commands.GetGatewayAddress;
private string _gateway;
public string Gateway => _gateway;
public MulticastGetGatewayAddress(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public MulticastGetGatewayAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
base.WholePackage();
response.GetParameter(FIRST_PARAMETER_OFFSET, out _gateway);
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} " });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} Gateway: {_gateway}" });
}
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastIdentify : MulticastCommandBase
{
protected override Commands Command => Commands.Identify;
public MulticastIdentify(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public MulticastIdentify(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac}" });
}
}
}

View File

@@ -0,0 +1,61 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
public class GetRealtimeSamplesSLICE2 : GetRealtimeSamples
{
public GetRealtimeSamplesSLICE2(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock) { LogCommands = false; }
public GetRealtimeSamplesSLICE2(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec) { LogCommands = false; }
protected override CommandReceiveAction WholePackage()
{
try
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
// Figure out the number of samples returned
var samplesReturned = (response.ParameterLength - 8) / (_channels * 2);
_samplesReturned = samplesReturned;
_data = new List<short[]>(_channels);
// Grab the sample number
if (response.ParameterLength > 0)
{
response.GetParameter(0, out _sampleNumber);
}
// Create the data arrays by channel
for (var i = 0; i < _channels; i++)
{
_data.Add(new short[samplesReturned]);
}
// Grab the data
var parameter = 8;
for (var sample = 0; sample < samplesReturned; sample++)
{
for (var channel = 0; channel < _channels; channel++)
{
response.GetParameter(parameter, out ushort val);
//changed from unsigned to signed
_data[channel][sample] = (short)((((val & 0x00FF) << 8) | ((val >> 8) & 0x00FF)) + 0x8000);
parameter += 2;
}
}
return CommandReceiveAction.StopReceiving;
}
}
catch
{
_samplesReturned = 0;
}
return CommandReceiveAction.StopReceiving;
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastSetIpAddress : MulticastCommandBase
{
const int COMMAND_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE + IP_ADDR_SIZE;
protected override Commands Command => Commands.SetIpAddress;
private string _ip;
public string Ip { set { _ip = value; command.SetParameter(FIRST_PARAMETER_OFFSET, _ip); } }
public MulticastSetIpAddress(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public MulticastSetIpAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} IP: {_ip}" });
}
}
}

View File

@@ -0,0 +1,43 @@
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
/// <summary>
/// this interface describes objects that are able to get realtime samples from
/// SLICE devices, the implementation differs based on whether it's using streaming
/// or is a SLICE6 device, etc, but all still operate through the same interface
/// </summary>
public interface IGetRealtimeSamples
{
/// <summary>
/// returns the sample number for the first sample, with all samples after that being consecutive
/// </summary>
ulong SampleNumber { get; }
ulong TimeStamp { get; }
ulong SequenceNumber { get; }
/// <summary>
/// returns all samples for the given channel
/// </summary>
/// <param name="zeroBasedChannel"></param>
/// <returns></returns>
short[] GetChannelData(int zeroBasedChannel);
/// <summary>
/// right now this holds the total channel count for the unit
/// </summary>
ushort Channels { get; set; }
/// <summary>
/// the count of samples per channel that were returned
/// if return value is 10 and there's 10 channels, there's 100 samples, or 10 samples per 10 channels
/// </summary>
int SamplesReturned { get; }
/// <summary>
/// whether to log the command or not
/// (not applicable on streaming mode as no command is executed)
/// default is normally false otherwise the log will be spammy
/// </summary>
bool LogCommands { get; set; }
/// <summary>
/// this is the execute that retrieves samples
/// </summary>
void SyncExecute();
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SLICECommands")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SLICECommands")]
[assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("B97BAF22-3B93-4187-9438-848AC714A144")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.06.0081")]
[assembly: AssemblyFileVersion("1.06.0081")]

View File

@@ -0,0 +1,307 @@
using System;
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
/// <summary>
/// these classes was ported from FWTU
/// </summary>
public class StreamConfigUDPGet : RealtimeCommandBase
{
private const int COMMAND_PAYLOAD_SIZE = 65;
protected override Commands _Command => Commands.I106StreamConfigGet;
private byte _stream_profile_number;
private byte[] _udpipport;
private ushort _timechannelid;
private ushort _datachannelid;
private uint _tmnsPcmSubFrameId; // _tmns0;
private uint _tmnsMsgId; // _tmns1;
private uint _tmnsPcmMinorPerMajor; // _tmns2;
private uint _tmnsTmatsPortNumber; // _tmns3;
private uint _ienaUdpSrcPortNumber; // _tmns4;
private uint _udpRsv1; // _tmns5;
private uint _udpRsv2; // _tmns6;
private uint _udpRsv3; // _tmns7;
public byte Stream_Profile_Number
{
get => _stream_profile_number;
set { _stream_profile_number = value; command.SetParameter(0, _stream_profile_number); }
}
public byte[] UdpIpPort
{
get { return _udpipport; }
set { _udpipport = value; command.SetParameter(1, _udpipport); }
}
public ushort TimeChannelID
{
get => _timechannelid;
set { _timechannelid = value; command.SetParameter(29, _timechannelid); }
}
public ushort DataChannelID
{
get => _datachannelid;
set { _datachannelid = value; command.SetParameter(31, _datachannelid); }
}
public uint TMNS_PCMSUBFRAMEID
{
get => _tmnsPcmSubFrameId;
set
{
_tmnsPcmSubFrameId = value;
command.SetParameter(33, _tmnsPcmSubFrameId);
}
}
public uint TMNS_MSGID
{
get { return _tmnsMsgId; }
set
{
_tmnsMsgId = value; command.SetParameter(37, _tmnsMsgId);
}
}
public uint TMNS_PCMINORPERMAJOR
{
get => _tmnsPcmMinorPerMajor;
set
{
_tmnsPcmMinorPerMajor = value; command.SetParameter(41, _tmnsPcmMinorPerMajor);
}
}
public uint TMNS_TMATSPORTNUMBER
{
get => _tmnsTmatsPortNumber;
set
{
_tmnsTmatsPortNumber = value; command.SetParameter(45, _tmnsTmatsPortNumber);
}
}
public uint IENAUDP_PortNumber
{
get => _ienaUdpSrcPortNumber;
set
{
_ienaUdpSrcPortNumber = value; command.SetParameter(49, _ienaUdpSrcPortNumber);
}
}
public uint TMNS5
{
get => _udpRsv1;
set
{
_udpRsv1 = value; command.SetParameter(53, _udpRsv1);
}
}
public uint TMNS6
{
get => _udpRsv2;
set
{
_udpRsv2 = value; command.SetParameter(57, _udpRsv2);
}
}
public uint TMNS7
{
get => _udpRsv3;
set
{
_udpRsv3 = value; command.SetParameter(61, _udpRsv3);
}
}
public StreamConfigUDPGet(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public StreamConfigUDPGet(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
if (response.ParameterLength > 0)
{
response.GetParameter(0, out _stream_profile_number);
_udpipport = new byte[29];
for (int i = 0; i < 28; i++)
{
response.GetParameter(1 + i, out _udpipport[i]);
}
response.GetParameter(29, out _timechannelid);
response.GetParameter(31, out _datachannelid);
response.GetParameter(33, out _tmnsPcmSubFrameId);
response.GetParameter(37, out _tmnsMsgId);
response.GetParameter(41, out _tmnsPcmMinorPerMajor);
response.GetParameter(45, out _tmnsTmatsPortNumber);
response.GetParameter(49, out _ienaUdpSrcPortNumber);
response.GetParameter(53, out _udpRsv1);
response.GetParameter(57, out _udpRsv2);
response.GetParameter(61, out _udpRsv3);
}
else { _stream_profile_number = 0; }
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"Stream Profile Number: {_stream_profile_number}" });
lines.Add(new List<string>() { $"UDP IP PORT: {_udpipport}" });
lines.Add(new List<string>() { $"Time Channel ID: {_timechannelid}" });
lines.Add(new List<string>() { $"Data Channel ID: {_timechannelid}" });
lines.Add(new List<string>() { $"TMNS: {_tmnsPcmSubFrameId}, {_tmnsMsgId}, {_tmnsPcmMinorPerMajor}, {_tmnsTmatsPortNumber}, {_ienaUdpSrcPortNumber}, {_udpRsv1}, {_udpRsv2}, {_udpRsv3}," });
}
}
public class StreamConfigUDPSet : RealtimeCommandBase
{
const int COMMAND_PAYLOAD_SIZE = 74;
protected override RealtimeCommandBase.Commands _Command
{
get { return Commands.I106StreamConfigSet; }
}
private byte _stream_profile_number;
private byte[] _udpipport;
private ushort _irig106config0;
private ushort _irig106config1;
private uint _tmnsPcmSubFrameId; // _tmns0;
private uint _tmnsMsgId; // _tmns1;
private uint _tmnsPcmMinorPerMajor; // _tmns2;
private uint _tmnsTmatsPortNumber; // _tmns3;
private uint _ienaUdpSrcPortNumber; // _tmns4;
private uint _udpRsv1; // _tmns5;
private uint _udpRsv2; // _tmns6;
private uint _udpRsv3; // _tmns7;
public byte Stream_Profile_Number
{
get => _stream_profile_number;
set { _stream_profile_number = value; command.SetParameter(0, _stream_profile_number); }
}
public byte[] UdpIpPort
{
get => _udpipport;
set
{
_udpipport = value;
command.SetParameter(1, _udpipport);
}
}
public ushort Irig106Config0
{
get => _irig106config0;
set
{
_irig106config0 = value; command.SetParameter(29, _irig106config0);
}
}
public ushort Irig106Config1
{
get => _irig106config1;
set
{
_irig106config1 = value; command.SetParameter(31, _irig106config1);
}
}
public uint TMNS_PCMSubFrameId
{
get => _tmnsPcmSubFrameId;
set
{
_tmnsPcmSubFrameId = value; command.SetParameter(33, _tmnsPcmSubFrameId);
}
}
public uint TMNS_MsgId
{
get => _tmnsMsgId;
set
{
_tmnsMsgId = value; command.SetParameter(37, _tmnsMsgId);
}
}
public uint TMNS_PCMMinorPerMajor
{
get => _tmnsPcmMinorPerMajor;
set
{
_tmnsPcmMinorPerMajor = value; command.SetParameter(41, _tmnsPcmMinorPerMajor);
}
}
public uint TMNS_TMATSPortNumber
{
get => _tmnsTmatsPortNumber;
set
{
_tmnsTmatsPortNumber = value; command.SetParameter(45, _tmnsTmatsPortNumber);
}
}
public uint IENAUDP_PortNumber
{
get => _ienaUdpSrcPortNumber;
set
{
_ienaUdpSrcPortNumber = value; command.SetParameter(49, _ienaUdpSrcPortNumber);
}
}
public uint TMNS5
{
get => _udpRsv1;
set
{
_udpRsv1 = value; command.SetParameter(53, _udpRsv1);
}
}
public uint TMNS6
{
get => _udpRsv2;
set
{
_udpRsv2 = value; command.SetParameter(57, _udpRsv2);
}
}
public uint TMNS7
{
get { return _udpRsv3; }
set
{
_udpRsv3 = value; command.SetParameter(61, _udpRsv3);
}
}
public StreamConfigUDPSet(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public StreamConfigUDPSet(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"Stream Profile Number: {_stream_profile_number}" });
lines.Add(new List<string>() { $"UDP IP PORT: {_udpipport}" });
lines.Add(new List<string>() { $"Irig Config: {_irig106config0}" });
lines.Add(new List<string>() { $"TMNS: {_tmnsPcmSubFrameId}, {_tmnsMsgId}, {_tmnsPcmMinorPerMajor}, {_tmnsTmatsPortNumber}, {_ienaUdpSrcPortNumber}, {_udpRsv1}, {_udpRsv2}, {_udpRsv3}," });
}
}
}

View File

@@ -0,0 +1,212 @@
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Utilities;
using DTS.DASLib.Command.Classes;
using System;
using System.Collections.Generic;
using System.Net;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastUdpQueryQATS : MulticastCommandBase
{
private const int COMMAND_PAYLOAD_SIZE = 63;
private const int RESPONSE_PAYLOAD_SIZE = 215; // 278;
protected override Commands Command => Commands.UdpQueryQTAS;
protected override bool StopAfterFirstMessage { get { return false; } }
private uint _deviceClass;
private byte _responseOption;
private IPAddress _address;
private int _port = (int)Ports.Response;
private void SetMulticastConfig()
{
IPAddress.TryParse(MulticastReceiveAddress, out _address);
string config = _address.ToString() + ":" + _port.ToString();
command.SetParameter(41, config);
}
public DFConstantsAndEnums.MultiCastDeviceClasses DeviceClass { set { _deviceClass = (uint)value; command.SetParameter(36, (int)_deviceClass); } }
public ResponseOptions ResponseOption { set { _responseOption = (byte)value; command.SetParameter(40, _responseOption); } }
public IPAddress Address { set { _address = value; SetMulticastConfig(); } }
public int Port { set { _port = value; SetMulticastConfig(); } }
private static object MyLock = new object();
public List<IUDPQATSEntry> QATSEntry { get; set; } = new List<IUDPQATSEntry>();
public MulticastUdpQueryQATS(ICommunication sock)
: base(sock)
{
Init();
}
public MulticastUdpQueryQATS(string macAddress)
: base(null)
{
Init(macAddress);
}
public MulticastUdpQueryQATS(int timeoutMillisec)
: base(null, timeoutMillisec)
{
Init();
}
public MulticastUdpQueryQATS(string macAddress, int timeoutMillisec)
: base(null, timeoutMillisec)
{
Init(macAddress);
}
public void Init(string macAddress = "")
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
HostMac = string.IsNullOrEmpty(macAddress) ? GetMacAddress() : macAddress;
command.SetParameter(HOST_MAC_ADDRESS_OFFSET, HostMac);
DeviceClass = DFConstantsAndEnums.MultiCastDeviceClasses.Any;
ResponseOption = ResponseOptions.AlwaysRespond;
ReceiveTimeoutMs = 5000;
SetMulticastConfig();
}
public MulticastUdpQueryQATS(ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
Init();
}
protected const int QATS_OFFSET = 74;
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
var responseHostMac = string.Empty;
response.GetParameter(HOST_MAC_ADDRESS_OFFSET, out responseHostMac);
if ((null == responseHostMac) || !HostMac.Equals(responseHostMac))
{
response.Status = DFConstantsAndEnums.CommandStatus.StatusInvalidPacket;
return CommandReceiveAction.StopReceiving;
}
if (response.ParameterLength < RESPONSE_PAYLOAD_SIZE)
{
response.Status = DFConstantsAndEnums.CommandStatus.StatusAttributeInvalidLength;
return CommandReceiveAction.StopReceiving;
}
var responseClientMac = string.Empty;
response.GetParameter(CLIENT_MAC_ADDRESS_OFFSET, out responseClientMac);
var qatsSerialNumber = string.Empty;
response.GetParameter(QATS_OFFSET, out qatsSerialNumber); /*! serial = 10B */
var armState = (byte)0;
response.GetParameter(QATS_OFFSET + 10, out armState); /*! 10 */
var armMode = (byte)0;
response.GetParameter(QATS_OFFSET + 11, out armMode); /*! 11 */
var started = (byte)0;
response.GetParameter(QATS_OFFSET + 12, out started); /*! 12 */
var eventTrigger = (byte)0;
response.GetParameter(QATS_OFFSET + 13, out eventTrigger); /*! 13 */
var faultFlags = (byte)0;
response.GetParameter(QATS_OFFSET + 14, out faultFlags); /*! 14 */
var sampleRate = (uint)0;
response.GetParameter(QATS_OFFSET + 15, out sampleRate); /*! 15 + 4 */
var totalSamples = 0UL;
response.GetParameter(QATS_OFFSET + 19, out totalSamples); /*! 19 + 8 */
var currentSample = 0UL;
response.GetParameter(QATS_OFFSET + 27, out currentSample); /*! 27 + 8 */
var eventNumber = (ushort)0;
response.GetParameter(QATS_OFFSET + 35, out eventNumber); /*! 35 + 2 */
var faultSampleNumber = 0UL;
response.GetParameter(QATS_OFFSET + 37, out faultSampleNumber); /*! 37 + 8 */
var legacyFaultFlag = (ushort)0;
response.GetParameter(QATS_OFFSET + 45, out legacyFaultFlag); /*! 45 + 2 */
var inputVoltage = 0F;
response.GetParameter(QATS_OFFSET + 47, out inputVoltage); /*! 47 + 4 */
var backupVoltage = 0F;
response.GetParameter(QATS_OFFSET + 51, out backupVoltage); /*! 51 + 4 */
var batterySoC = 0F;
response.GetParameter(QATS_OFFSET + 55, out batterySoC); /*! 55 + 4 */
var actualCurrentSample = 0UL;
response.GetParameter(QATS_OFFSET + 59, out actualCurrentSample); /*! 59 + 8 used by software to estimate remaining time in Circular mode */
var estimateMaxSamples = 0UL;
response.GetParameter(QATS_OFFSET + 67, out estimateMaxSamples); /*! 67 + 8 used by software to calculate current storage remaining */
/*! ^^^^ SPS Legacy end here ^^^^^^^*/
/*! Added by S6/S6A product */
var tiltSensorCh1 = (short)0;
response.GetParameter(QATS_OFFSET + 75, out tiltSensorCh1); /*! 75 + 2 */
var tiltSensorCh2 = (short)0;
response.GetParameter(QATS_OFFSET + 77, out tiltSensorCh2); /*! 77 + 2 */
var tiltSensorCh3 = (short)0;
response.GetParameter(QATS_OFFSET + 79, out tiltSensorCh3); /*! 79 + 2 */
var sysTempC = 0F;
response.GetParameter(QATS_OFFSET + 81, out sysTempC); /*! 71 + 4 */
// response.GetParameter(DOUBLE_MAC_ADDR_SIZE + 75, out _sensorData); /*! 75 + 12 channel 1 - 6 for S6/S6A */
/*! added for synchronization status in S6/S6A/S6DB/TSR-AIR ... */
var syncClockEnable = (byte)0;
response.GetParameter(QATS_OFFSET + 129, out syncClockEnable); /*! 129 + 1 */
var adcExtClockSyncEnable = (byte)0;
response.GetParameter(QATS_OFFSET + 130, out adcExtClockSyncEnable); /*! 130 + 1 */
var syncClockStatus = (byte)0;
response.GetParameter(QATS_OFFSET + 131, out syncClockStatus); /*! 131 + 1 */
var adcExtClockSyncStatus = (byte)0;
response.GetParameter(QATS_OFFSET + 132, out adcExtClockSyncStatus); /*! 132 + 1 */
var triggerSample = 0UL;
response.GetParameter(QATS_OFFSET + 133, out triggerSample); /*! 133 + 8 */
var curOffset = QATS_OFFSET + 133 + 4;
var stackChannelOffsetMV = new float[6];
for (var i = 0; i < 6; i++)
{
response.GetParameter(curOffset, out stackChannelOffsetMV[i]);
curOffset += 4;
}
var shuntDeviationPercent = new float[6];
for (var i = 0; i < 6; i++)
{
response.GetParameter(curOffset, out shuntDeviationPercent[i]);
curOffset += 4;
}
var timeStamp = DateTime.Now;
lock (MyLock)
{
QATSEntry.Add(
new UDPQATSEntry(responseHostMac, responseClientMac,
qatsSerialNumber, armState, armMode, started, eventTrigger, faultFlags, sampleRate, totalSamples,
currentSample, eventNumber, faultSampleNumber, legacyFaultFlag, inputVoltage,
backupVoltage, batterySoC, estimateMaxSamples, tiltSensorCh1, tiltSensorCh2, tiltSensorCh3,
sysTempC, syncClockEnable, adcExtClockSyncEnable, syncClockStatus, adcExtClockSyncStatus, triggerSample,
stackChannelOffsetMV,
shuntDeviationPercent,
timeStamp));
}
}
return CommandReceiveAction.StopReceiving;
}
/// <summary>
/// returns any waiting QATS, clear the list
/// </summary>
/// <returns></returns>
public IUDPQATSEntry[] GetUDPQATs()
{
lock (MyLock)
{
var quats = QATSEntry.ToArray();
QATSEntry.Clear();
return quats;
}
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>() { string.Format("UdpQueryQATS: [{0}] {1} : {1}", HostMac, _address, _port) });
}
}
}

View File

@@ -0,0 +1,188 @@
using System;
using System.Text;
using DTS.Common.Enums.Communication;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
using DTS.Common.Utilities;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// This was ported from FirmwareTestUtility where it was written by Loc Pham
/// it is being included for
/// 10573 implement SW side of single command/streaming download
/// this command can be used to collect data that has been collecting in a buffer
/// from download streaming
/// </summary>
public class GetNextDownloadStreamDataSamples : EventDataCommands
{
protected override Commands Command => Commands.GetNextDownloadStreamDataSamples;
public GetNextDownloadStreamDataSamples(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
baseCommand = new CommandPacket();
LogCommands = false;
baseCommand.SetCommand((byte)Commands.GetNextDownloadStreamDataSamples, "GetNextDownloadStreamDataSamples");
}
public GetNextDownloadStreamDataSamples(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout)
: base(sock, msTimeout)
{
baseCommand = new CommandPacket();
LogCommands = false;
baseCommand.SetCommand((byte)Commands.GetNextDownloadStreamDataSamples, "GetNextDownloadStreamDataSamples");
}
public DownloadByteConverter DlData { get; private set; }
private ushort _lastSequenceProcessed = ushort.MaxValue;
private const int MAX_SEQUENCE_DIFF = 1000;
public void ProcessData()
{
var bytes = baseResponse.ToBytes();
var headerCrc = response.HeaderCRC;
response.ComputeCRCs();
if (headerCrc != response.HeaderCRC)
{
DlData = null;
return;
}
DlData = new DownloadByteConverter(bytes);
if (null == DlData) { return; }
if (_lastSequenceProcessed == DlData.SeqNumber)
{
DlData = null;
return;
}
var delta = Math.Abs(DlData.SeqNumber - _lastSequenceProcessed);
if (delta > MAX_SEQUENCE_DIFF && ushort.MaxValue != _lastSequenceProcessed && 0 != DlData.SeqNumber)
{
//per loc we shouldn't get here, the old code in the FWTU would apparently unintentionally throw an exception
//I've preserved that code in comments below
throw new Exception("sequence number overflow");
//DlData = null;
//_lastSequenceProcessed = DlData.SeqNumber;
//return;
}
_lastSequenceProcessed = DlData.SeqNumber;
}
/// <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
{
DlData = null;
// 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);
}
else if (baseResponse.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
// didn't go well
var msg = MakeLogString("SyncExecute: response.Status = " + baseResponse.Status);
LogCommand(false);
switch (baseResponse.Status)
{
case DFConstantsAndEnums.CommandStatus.StatusInvalidModeForCommand:
throw new CommandException(CommandErrorReason.InvalidMode, msg);
case DFConstantsAndEnums.CommandStatus.StatusUnimplemented:
case DFConstantsAndEnums.CommandStatus.StatusInvalidCommand:
case 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);
LogCommand(false);
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
}
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveTimeout:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
}
case CommunicationConstantsAndEnums.CommunicationResult.SendFailed:
case CommunicationConstantsAndEnums.CommunicationResult.SendTimeout:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.SendFailed, msg);
}
default:
{
var msg = MakeLogString("SyncExecute: Unknown ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new Exception(msg);
}
}
}
finally
{
recorder.ExecuteIsBusy = false;
}
}
}
}

View File

@@ -0,0 +1,559 @@
using System;
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE
{
public abstract class FirmwareUpdateCommands : CommandBase
{
protected enum Commands
{
Reserved = 0x00,
QueryFirmwareUpdateBlockSize = 0x01,
QueryBootloaderVersion = 0x02,
SwitchToFirmwareUpdateMode = 0x03,
BeginFirmwareUpdate = 0x04,
ProgramFirmwareUpdateBlock = 0x05,
FinishFirmwareUpdate = 0x06,
Reboot = 0x07,
QueryInFirmwareUpdateMode = 0x08,
// added to support slice pro (Bridge/IEPE) firmware update via USB.
Load_SliceProStackFirmwareImage = 0x09, // CMDFW_LOAD_STACK_FW, // = 0x09, loading (in 400-byte blocks) firmware image to base NAND.
Query_SliceProStackFirmwareImage = 0x0A, // CMDFW_QUERY_STACK_FW, // = 0x0A, reading block (in 400-byte blocks) of firmware image from base NAND at a time.
Query_SliceProStackFirmwareCRC = 0x0B, // CMDFW_QUERY_STACK_FW_CRC, // = 0x0B, read firmware CRC for validation purpose.
Start_SliceProStackFirmwareUpdate = 0x0C, // CMDFW_START_STACK_FW_UPDADE, // = 0x0C, stack module to be upgraded with firmware.
Stop_SliceProStackFirmwareUpdate = 0x0D, // CMDFW_STOP_STACK_FW_UPDADE, // = 0x0D, stop firmware upgrade for after completes the on-going one.
Query_SliceProStackFirmwareUpdateMode = 0x0E, // CMDFW_QUERY_STACK_FW_UPDATE_MODE, // = 0x0E, polling updatae mode from stack
Set_SliceProStackFirmwareUpdateMode = 0x0F, // CMDFW_SET_STACK_FW_UPDATE_MODE, // = 0x0F, Set stack module to update mode
MAX_CMDFW_COMMAND // = 0x10
};
public enum FirmwareMode
{
FW = 0,
BL = 1,
BLL = 2,
};
//protected const int MIN_SLICE2_FILEDATA_PROTOCOL = 130; //SLICE 2 Protocol cmd
protected const int MAX_FILE_ID = 30; // user = 10, firmware = 20, max internally = 65. 10;
protected const int MAX_FILE_LENGTH = 400;
protected abstract Commands _Command { get; }
protected FirmwareUpdateCommands(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
protected FirmwareUpdateCommands(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
}
public class QueryFirmwareUpdateBlockSize : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.QueryFirmwareUpdateBlockSize;
private ushort _size;
public ushort BlockSize => _size;
public QueryFirmwareUpdateBlockSize(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
_size = 0;
}
public QueryFirmwareUpdateBlockSize(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
_size = 0;
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _size);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>()
{
$"BlockSize: {BlockSize}"
});
}
}
public class QueryBootloaderVersion : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.QueryBootloaderVersion;
private string _version = string.Empty;
public string Version => _version;
public QueryBootloaderVersion(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryBootloaderVersion(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _version);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"Version: {Version}"
});
}
}
public class SwitchToFirmwareUpdateMode : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.SwitchToFirmwareUpdateMode;
public SwitchToFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public SwitchToFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class BeginFirmwareUpdate : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.BeginFirmwareUpdate;
public BeginFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public BeginFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class ProgramFirmwareUpdateBlock : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.ProgramFirmwareUpdateBlock;
private uint _address;
private ushort _blockcrc;
private ushort _upperlower;
private byte[] _data;
public uint BlockBaseAddress
{
get => _address;
set
{
_address = value;
command.SetParameter(0, _address);
}
}
public ushort BlockSize { get; private set; }
public ushort BlockCRC16
{
get => _blockcrc;
set
{
_blockcrc = value;
command.SetParameter(6, _blockcrc);
}
}
public bool Upper
{
get => _upperlower == 1 ? true : false;
set
{
if (value)
{
_upperlower = 1;
command.SetParameter(8, _upperlower);
}
}
}
public byte[] Data
{
get => _data;
set
{
if (null == value)
{
return;
}
_data = value;
if (command.Parameter.Length < value.Length + 10)
{
var newparameter = new byte[value.Length + 10];
BlockSize = (ushort)value.Length;
command.SetParameter(4, BlockSize);
Buffer.BlockCopy(command.Parameter, 0,
newparameter, 0, 10);
command.Parameter = newparameter;
Buffer.BlockCopy(_data, 0, command.Parameter, 10, _data.Length);
}
}
}
public ProgramFirmwareUpdateBlock(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[10];
Upper = false;
}
public ProgramFirmwareUpdateBlock(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[10];
Upper = false;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>() { $"BlockBaseAddress: {BlockBaseAddress}, BlockSize: {BlockSize}, BlockCRC16: {BlockCRC16}, Upper: {Upper}" });
}
}
public class FinishFirmwareUpdate : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.FinishFirmwareUpdate;
private ushort _imagecrc;
public ushort ImageCRC16
{
get => _imagecrc;
set
{
_imagecrc = value;
command.SetParameter(0, _imagecrc);
}
}
public FinishFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[2];
}
public FinishFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[2];
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>() { $"ImageCRC16: {ImageCRC16}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"ImageCRC16: {ImageCRC16}"
});
}
}
public class Reboot : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.Reboot;
public Reboot(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public Reboot(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class QueryInFirmwareUpdateMode : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.QueryInFirmwareUpdateMode;
private byte _updateMode = (byte)FirmwareMode.FW;
public bool InUpdateMode => FirmwareMode.FW != (FirmwareMode)_updateMode;
public bool IsFwMode => FirmwareMode.FW == (FirmwareMode)_updateMode;
public bool IsBlMode => FirmwareMode.BL == (FirmwareMode)_updateMode;
public bool IsBllMode => FirmwareMode.BLL == (FirmwareMode)_updateMode;
public FirmwareMode Mode => (FirmwareMode)_updateMode;
public QueryInFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryInFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _updateMode);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
string.Format($"UpdateMode: {(FirmwareMode)_updateMode}")
});
}
}
/// <summary>
///These stack firmware command updates need at least protocol version 137
///No parameter. All slice in bootloader mode will be updated with new firmware.
/// </summary>
///
public class Load_SliceProStackFirmwareImage : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.Load_SliceProStackFirmwareImage;
#region Private Variables
private readonly ushort _fileID; //Byte 0-1: 16-bit file ID ranges from 1-10.
private uint _startByteCount;
private byte[] _data;
private static byte PARAM_NUM = 6;
#endregion
#region Command Parameters
public uint StartByteCount
{
get => _startByteCount;
set { _startByteCount = value; command.SetParameter(2, _startByteCount); }
}
public byte[] Data
{
get => _data;
set
{
if (null == value)
{
return;
}
if (MAX_FILE_LENGTH < value.Length)
{
throw new NotImplementedException();
}
_data = value;
//if (this.command.Parameter.Length < value.Length+ PARAM_NUM)
//{
byte[] newparameter = new byte[value.Length + PARAM_NUM];
Buffer.BlockCopy(command.Parameter, 0, newparameter, 0, PARAM_NUM);
Size = value.Length;
command.Parameter = newparameter;
Buffer.BlockCopy(_data, 0, command.Parameter, PARAM_NUM, _data.Length);
//}
}
}
public int Size { get; private set; }
public int MaximumFileStreamBytes => MAX_FILE_LENGTH;
#endregion
#region Command Functions
public Load_SliceProStackFirmwareImage(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[PARAM_NUM];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
_data = null;
_fileID = 20;
command.SetParameter(0, _fileID);
_startByteCount = 0;
command.ShouldLog = false;
}
public Load_SliceProStackFirmwareImage(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[PARAM_NUM];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
_data = null;
_fileID = 20;
command.SetParameter(0, _fileID);
_startByteCount = 0;
command.ShouldLog = false;
}
#endregion
#region Log Functions
public override void CommandToString(ref List<List<string>> lines)
{
lines.Add(new List<string>() { $"Store ID: {_fileID}, Start Byte: {StartByteCount}, End Byte: {Size + StartByteCount}" });
}
public void LogResponse()
{
LogCommand(false);
}
#endregion
}
public class Start_SliceProStackFirmwareUpdate : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.Start_SliceProStackFirmwareUpdate;
public Start_SliceProStackFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
public Start_SliceProStackFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
}
public class Set_SliceProStackFirmwareUpdateMode : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.Set_SliceProStackFirmwareUpdateMode;
private int _sliceCount = 0;
private byte[] _sliceProUpdateMode;
public int SliceModuleCount
{
get => _sliceCount;
set
{
_sliceCount = value;
_sliceProUpdateMode = new byte[_sliceCount];
}
}
public byte[] SliceModuledateMode
{
get => _sliceProUpdateMode;
set
{
for (int i = 0; i < _sliceCount; i++)
{
_sliceProUpdateMode[i] = value[i];
}
command.Parameter = _sliceProUpdateMode;
}
}
public Set_SliceProStackFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
public Set_SliceProStackFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
}
public class Get_SliceProStackFirmwareUpdateMode : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.Query_SliceProStackFirmwareUpdateMode;
public int SliceModuleCount { get; private set; } = 0;
public byte[] SliceModuledateMode { get; private set; }
public Get_SliceProStackFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
public Get_SliceProStackFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
SliceModuleCount = response.Parameter.Length;
SliceModuledateMode = new byte[SliceModuleCount];
for (int i = 0; i < SliceModuleCount; i++)
{
response.GetParameter(i, out SliceModuledateMode[i]);
}
}
return CommandReceiveAction.StopReceiving;
}
}
}

View File

@@ -0,0 +1,15 @@
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class QueryEventDataReport : ICommandReport
{
public object CallbackObject { get; set; }
public CommandStatus Status { get; set; }
public short[][] Data { get; set; }
public QueryEventDataReport(CommandStatus status, object cbData)
{
Status = status;
CallbackObject = cbData;
}
}
}

View File

@@ -0,0 +1,619 @@
using System;
using System.Collections.Generic;
using System.Linq;
using DTS.Common;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE
{
public abstract class Ptp1588Commands : CommandBase
{
public enum PtpClockType
{
SlaveTransparentClock = 0,
MasterTransparentClock = 1,
BoundaryClock = 2,
};
public enum PtpMode
{
Slave = 0,
Master = 1,
Auto = 2,
};
public enum PtpDelayMechanism
{
Undefined = 0,
E2E = 1,
P2P = 2,
};
public enum PtpSyncStatus
{
NotSynced = 0,
Synced = 1,
};
public enum PtpTimestampUnits
{
AutoTrigger = 1,
Event = 3,
AdcStart = 2,
Pps = 5,
};
protected enum Commands
{
Reserved = 0x00,
SetMode = 0x01,
GetMode = 0x02,
SetOptions = 0x03,
GetSyncStatus = 0x04,
SetTime = 0x05,
GetTime = 0x06,
GetAutoTriggerTime = 0x07,
SetAutoTriggerTime = 0x08,
GetTimestamp = 0x09,
SetTriggerTimestamping = 0x0A,
SetAdcClockFrquency = 0x0B,
RunClockAdjustmentCalibration = 0x0C,
SetClockSyncConfig = 0x0d,
GetClockSyncConfig = 0x0e,
};
protected abstract Commands _Command { get; }
protected Ptp1588Commands(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.Ptp1588;
command.SetCommand((byte)_Command, _Command.ToString());
}
protected Ptp1588Commands(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Type = CommandPacket.CommandType.Ptp1588;
command.SetCommand((byte)_Command, _Command.ToString());
}
public static string ToTimestampString(uint s, uint ns)
{
return $"{s}.{ns,9:000000000}";
}
}
public class Ptp1588SetMode : Ptp1588Commands
{
const int COMMAND_PAYLOAD_SIZE = 4;
protected override Commands _Command => Commands.SetMode;
private ushort _clock_type = 0;
private ushort _delay_mechanism = 0;
public void SetClockType(PtpClockType clockType)
{
_clock_type = (ushort)clockType;
command.SetParameter(0, _clock_type);
}
public void SetDelayMechanism(PtpDelayMechanism delayMechanism)
{
_delay_mechanism = (ushort)delayMechanism;
command.SetParameter(2, _delay_mechanism);
}
public Ptp1588SetMode(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public Ptp1588SetMode(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public override void CommandToString(ref List<List<string>> list)
{
base.CommandToString(ref list);
list.Add(new List<string>() { $"Mode: {_clock_type} DelayMechanism: {_delay_mechanism}" });
}
}
public class Ptp1588GetMode : Ptp1588Commands
{
private const int COMMAND_PAYLOAD_SIZE = 4;
protected override Commands _Command => Commands.GetMode;
private ushort _clock_type = 0;
private ushort _delay_mechanism = 0;
public PtpClockType ClockType => (PtpClockType)_clock_type;
public PtpDelayMechanism DelayMechanism => (PtpDelayMechanism)_delay_mechanism;
public Ptp1588GetMode(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public Ptp1588GetMode(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _clock_type);
response.GetParameter(2, out _delay_mechanism);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"ClockType: {ClockType}" });
}
}
public class Ptp1588GetSyncStatus : Ptp1588Commands
{
protected override Commands _Command => Commands.GetSyncStatus;
private int _ofm;
private int _adj;
public PtpSyncStatus SyncStatus { get; private set; }
public int OFM => _ofm;
public int FreqAdj => _adj;
public Ptp1588GetSyncStatus(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[5];
}
public Ptp1588GetSyncStatus(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[5];
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
if (response.ParameterLength > 6)
{
response.GetParameter(0, out byte status);
SyncStatus = (PtpSyncStatus)status;
response.GetParameter(1, out _ofm);
response.GetParameter(5, out _adj);
}
else { SyncStatus = PtpSyncStatus.NotSynced; }
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"Status: {SyncStatus} OFM: {OFM} ns Adj: {FreqAdj}" });
}
}
public class Ptp1588SetTime : Ptp1588Commands
{
protected override Commands _Command => Commands.SetTime;
private uint _s;
private uint _ns;
public void SetSeconds(uint seconds)
{
_s = seconds;
command.SetParameter(0, _s);
}
public void SetNanoseconds(uint ns)
{
_ns = ns;
command.SetParameter(4, _ns);
}
public Ptp1588SetTime(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[8];
}
public Ptp1588SetTime(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[8];
}
public override void CommandToString(ref List<List<string>> list)
{
base.CommandToString(ref list);
list.Add(new List<string>() { $"Time: {_s}.{_ns,9:000000000}" });
}
}
public class Ptp1588GetTime : Ptp1588Commands
{
protected override Commands _Command => Commands.GetTime;
private uint _s;
private uint _ns;
public uint Seconds => _s;
public uint Nanoseconds => _ns;
public string Timestamp => ToTimestampString(_s, _ns);
public Ptp1588GetTime(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[8];
}
public Ptp1588GetTime(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[8];
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _s);
response.GetParameter(4, out _ns);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { Timestamp });
}
}
public class Ptp1588SetAutoTriggerTime : Ptp1588Commands
{
protected override Commands _Command => Commands.SetAutoTriggerTime;
private uint _s;
private uint _ns;
public void SetSeconds(uint seconds)
{
_s = seconds;
command.SetParameter(0, _s);
}
public void SetNanoseconds(uint ns)
{
_ns = ns;
command.SetParameter(4, _ns);
}
public Ptp1588SetAutoTriggerTime(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[8];
}
public Ptp1588SetAutoTriggerTime(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[8];
}
public override void CommandToString(ref List<List<string>> list)
{
base.CommandToString(ref list);
list.Add(new List<string>() { $"Timestamp: {_s}.{_ns,9:000000000}" });
}
}
public class Ptp1588GetAutoTriggerTime : Ptp1588Commands
{
protected override Commands _Command => Commands.GetAutoTriggerTime;
private uint _s;
private uint _ns;
public uint Seconds => _s;
public uint Nanoseconds => _ns;
public string Timestamp => ToTimestampString(_s, _ns);
public Ptp1588GetAutoTriggerTime(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[8];
}
public Ptp1588GetAutoTriggerTime(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[8];
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _s);
response.GetParameter(4, out _ns);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { Timestamp });
}
}
public class Ptp1588GetTimestamp : Ptp1588Commands
{
protected override Commands _Command => Commands.GetTimestamp;
private byte _timestamp_unit;
private uint _s;
private uint _ns;
private byte _timestamp_valid;
public PtpTimestampUnits TimestampUnit { set { _timestamp_unit = (byte)value; command.SetParameter(0, _timestamp_unit); } }
public uint Seconds => _s;
public uint Nanoseconds => _ns;
public bool IsValid => Convert.ToBoolean(_timestamp_valid);
public string Timestamp => ToTimestampString(_s, _ns);
public Ptp1588GetTimestamp(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[1];
}
public Ptp1588GetTimestamp(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[1];
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _timestamp_valid);
response.GetParameter(1, out _s);
response.GetParameter(5, out _ns);
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> list)
{
base.CommandToString(ref list);
list.Add(new List<string>() { $"Timestamp Unit: {_timestamp_unit}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"Timestamp: {Timestamp}" });
}
}
public class Ptp1588SetEnableTimestamping : Ptp1588Commands
{
protected override Commands _Command => Commands.SetTriggerTimestamping;
private byte _enable;
public void SetEnable(bool enable)
{
_enable = Convert.ToByte(enable);
command.SetParameter(0, _enable);
}
public Ptp1588SetEnableTimestamping(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[1];
}
public Ptp1588SetEnableTimestamping(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[1];
}
public override void CommandToString(ref List<List<string>> list)
{
base.CommandToString(ref list);
list.Add(new List<string>() { $"Enable: {_enable}" });
}
}
public class Ptp1588SetAdcClockFrequency : Ptp1588Commands
{
private const int COMMAND_PAYLOAD_SIZE = 4;
protected override Commands _Command => Commands.SetAdcClockFrquency;
private uint _requestedFrequency;
private uint _actualFrequency;
public uint RequestedFrequency { set { _requestedFrequency = value; command.SetParameter(0, _requestedFrequency); } }
public Ptp1588SetAdcClockFrequency(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public Ptp1588SetAdcClockFrequency(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _actualFrequency);
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> list)
{
base.CommandToString(ref list);
list.Add(new List<string>() { $"Requested Frequency: {_requestedFrequency}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"Actual Frequency: {_actualFrequency}" });
}
}
public class Ptp1588RunClockAdjustmentCalibration : Ptp1588Commands
{
private const int COMMAND_PAYLOAD_SIZE = 3;
protected override Commands _Command => Commands.RunClockAdjustmentCalibration;
private byte _saveAtribute = 0;
private ushort _durationSeconds = 60;
public void SetDuration(ushort duration)
{
_durationSeconds = duration;
command.SetParameter(0, _durationSeconds);
}
public void SetSaveAttribute(bool b)
{
_saveAtribute = Convert.ToByte(b);
command.SetParameter(2, _saveAtribute);
}
public Ptp1588RunClockAdjustmentCalibration(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public Ptp1588RunClockAdjustmentCalibration(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public override void CommandToString(ref List<List<string>> list)
{
base.CommandToString(ref list);
list.Add(new List<string>() { $"Duration: {_durationSeconds} Save Attribute {_saveAtribute}" });
}
}
public class QueryClockSyncStatus : Ptp1588Commands
{
protected override Commands _Command
{
get { return Commands.GetClockSyncConfig; }
}
private byte _inputstate;
public byte InputState { get => _inputstate; }
private byte _outputstate;
public byte OutputState { get => _outputstate; }
private byte _clockSyncProfile;
private byte _syncstatus;
public byte SyncStatus { get => _syncstatus; }
public ClockSyncProfile ClockSyncProfile => (ClockSyncProfile)_clockSyncProfile;
private readonly List<InputClockSource> _inputSources = new List<InputClockSource>();
public List<InputClockSource> InputSources => _inputSources;
private readonly List<OutputClockSource> _outputSources = new List<OutputClockSource>();
public List<OutputClockSource> OutputSources => _outputSources;
public IDictionary<InputClockSource, bool> InputSyncStatus { get; } = new Dictionary<InputClockSource, bool>();
public QueryClockSyncStatus(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.QueryClockSyncStatus);
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError && response.ParameterLength > 1)
{
response.GetParameter(0, out _clockSyncProfile);
response.GetParameter(1, out _inputstate);
response.GetParameter(2, out _outputstate);
response.GetParameter(3, out _syncstatus);
var sources = Enum.GetValues(typeof(InputClockSource)).Cast<InputClockSource>().ToList();
for (int i = 1; i < sources.Count; i++)
{
// use source as a mask on status to get the current state (same bit structure)
InputSyncStatus.Add(sources[i], (_syncstatus & (byte)sources[i]) == (byte)sources[i]);
}
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { string.Format("Input source(s): {0}", string.Join(", ", InputSources.Select(source => source.ToString()))) });
lines.Add(new List<string>() { string.Format("Output source(s): {0}", string.Join(", ", OutputSources.Select(source => source.ToString()))) });
lines.Add(new List<string>() { string.Format("Input source synced: {0}", string.Join(", ", InputSyncStatus.Select(statuspair => statuspair.Key.ToString() + "-" + statuspair.Value.ToString()))) });
}
}
public class SetClockSyncConfig : Ptp1588Commands
{
protected override Commands _Command
{
get { return Commands.SetClockSyncConfig; }
}
public SetClockSyncConfig(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.SetClockSyncConfig);
}
protected override CommandReceiveAction WholePackage()
{
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { ResponseStatus == DFConstantsAndEnums.CommandStatus.StatusNoError ? "Set Clock Config Success" : "Set Clock Config Failure" });
}
}
}

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.EndRealtimeMode" Collapsed="true">
<Position X="0.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>RealtimeCommands\EndRealtimeMode.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.GetRealtimeSamples" Collapsed="true">
<Position X="6.25" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AEAAAAAABAAAEABAAAAABBAAAAAAAAAAAAAAgEIAEEA=</HashCode>
<FileName>RealtimeCommands\GetRealtimeSamples.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.GetRealtimeSamplesSLICE2" Collapsed="true">
<Position X="5" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAA=</HashCode>
<FileName>RealtimeCommands\GetRealtimeSamplesSLICE2.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.GetRealtimeSamplesSLICE6" Collapsed="true">
<Position X="7.25" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAA=</HashCode>
<FileName>RealtimeCommands\GetRealtimeSamplesSLICE6.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.RealtimeCommandBase" Collapsed="true">
<Position X="7.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>RealtimeCommands\RealtimeCommandBase.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.RealtimeStreamDecoder" Collapsed="true">
<Position X="0.5" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAABAACAAAAAAABAgAgAAAAAAQAAAAAAAAAAAAgAEAA=</HashCode>
<FileName>RealtimeCommands\RealtimeStreamDecoder.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.RealtimeStreamingNextSamples" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="2.25" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>EgABAACAAAAAAABAAAAABABAAAIBAAAAQAAAgAABEAA=</HashCode>
<FileName>RealtimeCommands\RealtimeStreamingNextSamples.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.RetrieveSampleAverage" Collapsed="true">
<Position X="2.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAABAQAAAAIAAAABBBAAAAAAAAgAAAAgEAAEEA=</HashCode>
<FileName>RealtimeCommands\RetrieveSampleAverage.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.RetrieveSingleSample" Collapsed="true">
<Position X="9.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAABAAAAAAAAAAABBAAAAAAAAAAAAAAAEAAEEA=</HashCode>
<FileName>RealtimeCommands\RetrieveSingleSample.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.StartRealtimeMode" Collapsed="true">
<Position X="11.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAACAAAAAAABAAAAAAAAAAABAAAAAAAAA=</HashCode>
<FileName>RealtimeCommands\StartRealtimeMode.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.StartRealtimeStreamingMode" Collapsed="true">
<Position X="14" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAQAAAAAA=</HashCode>
<FileName>RealtimeCommands\StartRealtimeStreamingMode.cs</FileName>
</TypeIdentifier>
</Class>
<Interface Name="DTS.DASLib.Command.SLICE.RealtimeCommands.IGetRealtimeSamples" Collapsed="true">
<Position X="0.5" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AgAAAAAAAAAAAABAAAAABAAAAAAAAAAAAAQAgAAAEAA=</HashCode>
<FileName>RealtimeCommands\IGetRealtimeSamples.cs</FileName>
</TypeIdentifier>
</Interface>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,134 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
public class GetRealtimeSamples : RealtimeCommandBase, IGetRealtimeSamples
{
protected override Commands _Command => Commands.GetRealtimeSamples;
protected ulong _sampleNumber;
/// <summary>
/// The first sample number of the samples being returned. The remaining samples in
/// the response packet will be numbered sequentially and without gaps from this number.
/// If 12 samples are returned, and SampleNumber is 83042, the first sample will be number
/// 83042, the second 83043, etc.
/// </summary>
public ulong SampleNumber => _sampleNumber;
protected ulong _timeStamp;
public ulong TimeStamp => _timeStamp;
protected ulong _sequenceNumber;
public ulong SequenceNumber => _sequenceNumber;
protected List<short[]> _data;
public short[] GetChannelData(int zeroBasedChannel)
{
return _data[zeroBasedChannel];
}
protected ushort _channels;
public ushort Channels
{
get
{
if (null == _data) return 0;
return _channels;
}
set => _channels = value;
}
protected int _samplesReturned;
/// <summary>
/// Contains the number of samples that were returned in this realtime packet. Can be 0!
/// </summary>
public int SamplesReturned => _samplesReturned;
public GetRealtimeSamples(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock, 2000)
{
// don't need to put anything in here ... its presense
// tells the firmware that we support multiple-sample
// realtime
command.Parameter = new byte[1];
}
/// <summary>
/// constructor for GetRealtimeSamples, a class implementing IGetRealtimeSamples
/// this class is capable of returning realtime samples
/// </summary>
/// <param name="sock"></param>
/// <param name="TimeoutMillisec"></param>
/// <param name="bPolling">whether realtime is using polling or not</param>
public GetRealtimeSamples(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec, bool bPolling = false)
: base(sock, TimeoutMillisec)
{
// don't need to put anything in here ... its presense
// tells the firmware that we support multiple-sample
// realtime
command.Parameter = new byte[1];
}
protected override CommandReceiveAction WholePackage()
{
try
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
// Figure out the number of samples returned
var samplesReturned = response.ParameterLength / (_channels * 2 + 8);
_samplesReturned = samplesReturned;
var unsignedData = new List<ushort[]>(_channels);
_data = new List<short[]>(_channels);
// Grab the sample number
if (response.ParameterLength > 0)
{
response.GetParameter(0, out _sampleNumber);
}
// Create the data arrays by channel
for (var i = 0; i < _channels; i++)
{
unsignedData.Add(new ushort[samplesReturned]);
_data.Add(new short[samplesReturned]);
}
// Grab the data
for (var sample = 0; sample < samplesReturned; sample++)
{
// Data order for a 9 channel stack
// 7 8 9 4 5 6 1 2 3 7 8 9 4 5 6 1 2 3 etc.
for (var channel = 0; channel < _channels; channel++)
{
var sliceNumber = channel / 3;
var sliceOffset = (_channels / 3 - sliceNumber - 1) * 3;
var channelInSlice = channel % 3;
var offset = sliceOffset + channelInSlice;
response.GetParameter(8 + sample * (8 + _channels * 2) + 2 * offset, out ushort val);
unsignedData[channel][sample] = val;
_data[channel][sample] = (short)(unsignedData[channel][sample] - 0x8000);
}
}
return CommandReceiveAction.StopReceiving;
}
}
catch
{
_samplesReturned = 0;
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string> { $"Sample number: {ResponseStatus}, Samples returned: {SampleNumber}, Time Stamp returned: {TimeStamp}, Sequence Number returned: {SequenceNumber}" });
}
}
}

View File

@@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Strings;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class QueryUARTEventInfo : EventDataCommands
{
protected override Commands Command => Commands.QueryUartEventInfo;
protected ushort _eventNumber;
protected ushort _dataPresent;
protected ushort _dataDownloaded;
protected ulong _totalByteCount;
protected ulong _triggerByteCount;
protected ulong _faultByteCount;
protected uint _startTimestamp;
protected uint _endTimestamp;
protected uint _baudrate;
public ushort EventNumber
{
get => _eventNumber;
set { _eventNumber = value; command.SetParameter(0, _eventNumber); }
}
public QueryUARTEventInfo(ICommunication sock) : base(sock)
{
command.Parameter = new byte[2];
_eventNumber = 0;
_dataPresent = 0;
_dataDownloaded = 0;
_totalByteCount = 0;
_triggerByteCount = 0;
_faultByteCount = 0;
_startTimestamp = 0;
_endTimestamp = 0;
_baudrate = 0;
command.ShouldLog = false;
}
public QueryUARTEventInfo(ICommunication sock, int timeoutMillisec) : base(sock, timeoutMillisec)
{
command.Parameter = new byte[2];
_eventNumber = 0;
_dataPresent = 0;
_dataDownloaded = 0;
_totalByteCount = 0;
_faultByteCount = 0;
_triggerByteCount = 0;
_startTimestamp = 0;
_endTimestamp = 0;
_baudrate = 0;
command.ShouldLog = false;
}
public bool DataPresent => 1 == _dataPresent;
public bool DataDownloaded => 1 == _dataDownloaded;
public ulong TotalByteCount => _totalByteCount;
public ulong TriggerByteCount => _triggerByteCount;
public ulong FaultByteCount => _faultByteCount;
public uint StartTimestamp => _startTimestamp;
public uint EndTimestamp => _endTimestamp;
public uint BaudRate => _baudrate;
public override void Execute(CommandCallback cb, object cbData)
{
// Do a little parameter checking
base.Execute(cb, cbData);
}
protected override CommandReceiveAction WholePackagePost()
{
// now send the data to the user
var stat = CommandStatus.Success;
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
var s = (int)response.Status;
APILogger.LogString("QueryUARTEventInfo.WholePackagePost: reporting failure, status==" + CommandPacketBase.StatusLabels[s] + " (0x" + s.ToString("X") + ")");
stat = CommandStatus.Failure;
}
var cbReport = new QueryEventDataReport(stat, UserCallbackData);
//cbReport.Data = new short[_channelsDownloaded][];
//for (var i = 0; i < _channelsDownloaded; i++)
// GetChannelData(i, out cbReport.Data[i]);
return UserCallback(cbReport);
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
return CommandReceiveAction.StopReceiving;
}
response.GetParameter(0, out ushort responseEventNum);
response.GetParameter(2, out _dataPresent);
response.GetParameter(4, out _dataDownloaded);
response.GetParameter(8, out _totalByteCount);
response.GetParameter(16, out _triggerByteCount);
response.GetParameter(24, out _faultByteCount);
response.GetParameter(32, out _startTimestamp);
response.GetParameter(36, out _endTimestamp);
response.GetParameter(40, out _baudrate);
return CommandReceiveAction.StopReceiving;
}
public override void SyncExecute()
{
// Do a little parameter checking
base.SyncExecute();
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"Event number: {EventNumber}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>
{
$"DataPresent: {DataPresent}, DataDownloaded: {DataDownloaded}, TotalByteCount: {TotalByteCount}, TriggerByteCount: {TriggerByteCount}, StartTimestamp: {StartTimestamp}, EndTimestamp: {EndTimestamp}"
});
}
public void LogResponse()
{
LogCommand(false);
}
}
}

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.DownloadByteConverter" Collapsed="true">
<Position X="2.25" Y="4" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAQAAAAAAAIREAAAAAQAAgAAAQAgAAAgQAAA=</HashCode>
<FileName>DownloadCommands\DownloadByteConverter.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.EventDataCommands" Collapsed="true">
<Position X="5" Y="0.5" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>DownloadCommands\EventDataCommands.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.GetNextDownloadStreamDataSamples" Collapsed="true">
<Position X="7.25" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>EgAAAAAAAAAAAAAAAAAABAQAAAABgAAAAAAAAAAAAAA=</HashCode>
<FileName>DownloadCommands\GetNextDownloadStreamDataSamples.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.QueryEventDataBase" Collapsed="true">
<Position X="0.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AkAAAAAghABIAAQBAIAABIRCAAAAAAgAAABAFFEgAEA=</HashCode>
<FileName>DownloadCommands\QueryEventDataBase.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.QueryEventDataReport" Collapsed="true">
<Position X="4" Y="4" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAEAAAAAAAAAAAAAAAAAAAAABAAAAAAAIAAAAA=</HashCode>
<FileName>DownloadCommands\QueryEventDataReport.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.QueryTotalEventCount" Collapsed="true">
<Position X="9.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABAQAAAAAAAAAAACAAEAAAEA=</HashCode>
<FileName>DownloadCommands\QueryTotalEventCount.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.ResetEventList" Collapsed="true">
<Position X="2.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>DownloadCommands\ResetEventList.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.StartDownloadStreamData" Collapsed="true">
<Position X="5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAgAAAAAABAAAABAAAAAAAAAoAAABAABAgAAA=</HashCode>
<FileName>DownloadCommands\StartDownloadStreamData.cs</FileName>
</TypeIdentifier>
</Class>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,643 @@
using System;
using System.Collections.Generic;
using System.Text;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Command.SLICE
{
public abstract class ArmCommands : CommandBase
{
protected enum Commands
{
Reserved = 0x00,
Arm = 0x01,
Disarm = 0x02,
EnableFaultChecking = 0x03,
DisableFaultChecking = 0x04,
QueryArmAndTriggerStatus = 0x05,
PrepareForDiagnostics = 0x06,
PrepareForDataCollection = 0x07,
BeginFlashErase = 0x08,
QueryFlashEraseStatus = 0x09,
InitializeHardwareLines = 0x0a,
};
protected abstract Commands _Command { get; }
protected ArmCommands(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.Arm;
command.SetCommand((byte)_Command, _Command.ToString());
}
protected ArmCommands(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Type = CommandPacket.CommandType.Arm;
command.SetCommand((byte)_Command, _Command.ToString());
}
}
public class Arm : ArmCommands
{
protected override Commands _Command => Commands.Arm;
public Arm(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public Arm(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
public DFConstantsAndEnums.CommandStatus ArmStatus { get; private set; } = DFConstantsAndEnums.CommandStatus.StatusNoError;
protected override CommandReceiveAction WholePackage()
{
switch (response.Status)
{
case DFConstantsAndEnums.CommandStatus.StatusNoError:
break;
default:
ArmStatus = response.Status;
break;
}
return CommandReceiveAction.StopReceiving;
}
}
public class EnableFaultChecking : ArmCommands
{
protected override Commands _Command => Commands.EnableFaultChecking;
public EnableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public EnableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class DisableFaultChecking : ArmCommands
{
protected override Commands _Command => Commands.DisableFaultChecking;
public DisableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public DisableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class QueryArmAndTriggerStatus : ArmCommands
{
protected override Commands _Command => Commands.QueryArmAndTriggerStatus;
public enum FaultFlags
{
IncomingStatusLineDropped = (1 << 0),
ADCBufferOverrun = (1 << 1),
FlashCRCError = (1 << 2),
TriggerBeforeStart = (1 << 3),
InputVoltageLow = (1 << 4),
InputVoltageHigh = (1 << 5),
BackupVoltageLow = (1 << 6),
BackupVoltageHigh = (1 << 7),
OutOfMemory = (1 << 8),
SquibResistanceOutOfRange = (1 << 9),
SafeSwitchUnplugged = (1 << 10),
SquibPowerOutOfRange = (1 << 11),
AutoSquibDisableActivated = (1 << 12)
}
private float _inputVoltage = 0;
public float InputVoltage => _inputVoltage;
private float _backupVoltage = 0;
public float BackupVoltage => _backupVoltage;
private byte _armstate;
private byte _armmode;
private byte _startrecordstatus;
private byte _triggerstatus;
private byte _faultstatus;
private uint _eventsamplerate;
private ulong _totalsamples;
private ulong _currentsample;
private ushort _currenteventnumber;
private ulong _faultsamplenumber;
private ushort _faultbits;
private float _batterySoc;
private float _systemTempC;
private ulong _actualCurrentSample;
private ulong _maxSampleAvailable;
private short _tsChannel1;
private short _tsChannel2;
private short _tsChannel3;
private short _sensorChannelA;
private short _sensorChannelB;
private short _sensorChannelC;
private short _sensorChannelD;
private short _sensorChannelE;
private short _sensorChannelF;
// for TOM
private float _squib1;
private float _squib2;
private float _squib3;
private float _squib4;
private float _squibP17V;
private float _squibP5V;
private float _squibP3p3V;
private float _squibN5V;
private bool _ptpEnable;
private bool _adcPtpClkEnable;
private bool _ptpSyncStatus;
private bool _adcClkSyncStatus;
private uint _extFaultId;
public ArmStates ArmState => (ArmStates)_armstate;
public enum ArmStates { Disarmed, Armed, Realtime, Diagnostics, FlashClear, Arming };
public byte ArmMode => _armmode;
public bool IsDiagnostics => (ArmStates)_armstate == ArmStates.Diagnostics;
public bool IsFlashClear => (ArmStates)_armstate == ArmStates.FlashClear;
public bool IsArming => (ArmStates)_armstate == ArmStates.Arming;
public bool IsArmed => (ArmStates)_armstate == ArmStates.Armed;
public bool IsInRealtime => (ArmStates)_armstate == ArmStates.Realtime;
public bool IsRecording => _startrecordstatus == 0x01;
public bool IsTriggered => _triggerstatus == 0x01;
public bool IsFaulted => _faultstatus == 0x01;
public uint EventSampleRate => _eventsamplerate;
public ulong TotalSamples => _totalsamples;
public ulong CurrentSample => _currentsample;
public ushort EventNumber => _currenteventnumber;
public ulong FaultSampleNumber => _faultsamplenumber;
public List<FaultFlags> CurrentFaultFlags { get; } = new List<FaultFlags>();
public int BatterySoc => (int)_batterySoc;
public float SystemTempC => _systemTempC;
public ulong ActualCurrentSample => _actualCurrentSample;
public ulong MaxSampleAvailable => _maxSampleAvailable;
public short TiltSensorChannel1 => _tsChannel1;
public short TiltSensorChannel2 => _tsChannel2;
public short TiltSensorChannel3 => _tsChannel3;
public short SensorChannelA => _sensorChannelA;
public short SensorChannelB => _sensorChannelB;
public short SensorChannelC => _sensorChannelC;
public short SensorChannelD => _sensorChannelD;
public short SensorChannelE => _sensorChannelE;
public short SensorChannelF => _sensorChannelF;
public float SquibResistance1 { get { return _squib1; } }
public float SquibResistance2 { get { return _squib2; } }
public float SquibResistance3 { get { return _squib3; } }
public float SquibResistance4 { get { return _squib4; } }
public float SquibPowerP17V { get { return _squibP17V; } }
public float SquibPowerP5V { get { return _squibP5V; } }
public float SquibPowerP3p3V { get { return _squibP3p3V; } }
public float SquibPowerN5V { get { return _squibN5V; } }
public bool PtpFunctionEnable { get { return _ptpEnable; } }
public bool AdcPtpClkEnable { get { return _adcPtpClkEnable; } }
public bool PtpClkSyncStatus { get { return _ptpSyncStatus; } }
public bool AdcClkSyncStatus { get { return _adcClkSyncStatus; } }
private List<QATSExtendedFault> _extendedFaultFlags = new List<QATSExtendedFault>();
public List<QATSExtendedFault> ExtendedFaultFlags { get { return _extendedFaultFlags; } }
public uint ExtendedFaultId { get { return _extFaultId; } }
public QueryArmAndTriggerStatus(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryArmAndTriggerStatus(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
private const int QUATS_MIN_LENGTH_INPUTVOLTAGE = 38;
private const int QUATS_MIN_LENGTH_BACKUPVOLTAGE = 42;
private const int QUATS_MIN_LENGTH_BATTERYSOC = 49;
private const int QUATS_MIN_LENGTH_ACTUALCURRENTSAMPLE = 57;
private const int QUATS_MIN_LENGTH_MAXSAMPLEAVAILABLE = 65;
private const int QUATS_MIN_LENGTH_TILTCHANNELDATA = 71;
private const int QUATS_MIN_LENGTH_SYSTEMTEMP = 75;
private const int QUATS_MIN_LENGTH_CHANNELADC = 87;
private const int QUATS_MIN_LENGTH_TOMSTATUS = 119;
private const int QUATS_MIN_LENGTH_CLKSTATUS = 123;
private const int QUATS_MIN_LENGTH_EXTFAULTID = 127;
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
if (response.ParameterLength > 1)
{
response.GetParameter(0, out _armstate);
response.GetParameter(1, out _armmode);
response.GetParameter(2, out _startrecordstatus);
response.GetParameter(3, out _triggerstatus);
response.GetParameter(4, out _faultstatus);
response.GetParameter(5, out _eventsamplerate);
response.GetParameter(9, out _totalsamples);
response.GetParameter(17, out _currentsample);
response.GetParameter(25, out _currenteventnumber);
response.GetParameter(27, out _faultsamplenumber);
//this is only valid for > 00E7, but that's long retired, so I'm enforcing it now
response.GetParameter(35, out _faultbits);
for (int i = 0; i < 16; i++)
{
if (0 != (_faultbits & (1 << i)))
{
CurrentFaultFlags.Add((FaultFlags)(1 << i));
}
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_INPUTVOLTAGE)
{
response.GetParameter(37, out _inputVoltage);
}
else
{
_inputVoltage = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_BACKUPVOLTAGE)
{
response.GetParameter(41, out _backupVoltage);
}
else
{
_backupVoltage = 0;
}
if (recorder.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.QueryBatterySOC)
&& response.ParameterLength >= QUATS_MIN_LENGTH_BATTERYSOC)
{
response.GetParameter(45, out _batterySoc);
}
else
{
_batterySoc = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_ACTUALCURRENTSAMPLE)
{
response.GetParameter(49, out _actualCurrentSample);
}
else
{
_actualCurrentSample = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_MAXSAMPLEAVAILABLE)
{
response.GetParameter(57, out _maxSampleAvailable);
}
else
{
_maxSampleAvailable = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_TILTCHANNELDATA)
{
response.GetParameter(65, out _tsChannel1);
response.GetParameter(67, out _tsChannel2);
response.GetParameter(69, out _tsChannel3);
}
else
{
_tsChannel1 = 0;
_tsChannel2 = 0;
_tsChannel3 = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_SYSTEMTEMP)
{
response.GetParameter(71, out _systemTempC);
}
else
{
_systemTempC = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_CHANNELADC)
{
response.GetParameter(75, out _sensorChannelA);
response.GetParameter(77, out _sensorChannelB);
response.GetParameter(79, out _sensorChannelC);
response.GetParameter(81, out _sensorChannelD);
response.GetParameter(83, out _sensorChannelE);
response.GetParameter(85, out _sensorChannelF);
}
else
{
_sensorChannelA = 0;
_sensorChannelB = 0;
_sensorChannelC = 0;
_sensorChannelD = 0;
_sensorChannelE = 0;
_sensorChannelF = 0;
}
// hack for TOM
if (response.ParameterLength >= QUATS_MIN_LENGTH_TOMSTATUS)
{
response.GetParameter(87, out _squib1);
response.GetParameter(91, out _squib2);
response.GetParameter(95, out _squib3);
response.GetParameter(99, out _squib4);
response.GetParameter(103, out _squibP17V);
response.GetParameter(107, out _squibP5V);
response.GetParameter(111, out _squibP3p3V);
response.GetParameter(115, out _squibN5V);
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_CLKSTATUS)
{
response.GetParameter(119, out _ptpEnable);
response.GetParameter(120, out _adcPtpClkEnable);
response.GetParameter(121, out _ptpSyncStatus);
response.GetParameter(122, out _adcClkSyncStatus);
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_EXTFAULTID)
{
response.GetParameter(123, out _extFaultId);
}
for (int i = 0; i < 32; i++)
{
if (0 != (_extFaultId & (1 << i)))
{
_extendedFaultFlags.Add((QATSExtendedFault)(1 << i));
}
}
}
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"Event number: {EventNumber}, Arm Mode: {ArmMode}" });
lines.Add(new List<string>() { $"Armed: {IsArmed}, Started: {IsRecording}, Triggered: {IsTriggered}, Faulted: {IsFaulted}, Diagnostics: {IsDiagnostics}, FlashClear: {IsFlashClear}, Arming: {IsArming}, ArmState: {_armstate}" });
lines.Add(new List<string>() { $"Samplerate: {EventSampleRate}, Current Sample: {CurrentSample}, Total Samples: {TotalSamples}, Fault Sample Number: {FaultSampleNumber}" });
lines.Add(new List<string>() { $"Input Voltage: {InputVoltage.ToString("N3")}V, Backup Voltage: {BackupVoltage.ToString("N3")}V, Backup Percentage Remaining: {BatterySoc}%" });
lines.Add(new List<string>() { $"System Temp: {SystemTempC}C, Actual Current Sample: {ActualCurrentSample}, Max Sample Available: {MaxSampleAvailable}" });
lines.Add(new List<string>() { $"Tilt Ch1: {TiltSensorChannel1}, Tilt Ch2: {TiltSensorChannel2}, Tilt Ch3: {TiltSensorChannel3}" });
lines.Add(new List<string>() { $"Squib Ch1: {SquibResistance1}, Squib Ch2: { SquibResistance2}, Squib Ch3: { SquibResistance3}, Squib Ch4: { SquibResistance4}" });
lines.Add(new List<string>() { $"Squib P17V: {SquibPowerP17V}, Squib PV5: { SquibPowerP5V}, Squib P3p3V: { SquibPowerP3p3V}, Squib N5V: { SquibPowerN5V}" });
lines.Add(new List<string>() { $"PTP Enabled: {PtpFunctionEnable}, PTP Clk Enable: {AdcPtpClkEnable}, PTP Clk Sync Status: {PtpClkSyncStatus}, ADC Clk Sync Status: {AdcClkSyncStatus}" });
var sb = new StringBuilder(50);
sb.AppendFormat("Fault Flags: ");
if (null != CurrentFaultFlags && CurrentFaultFlags.Count > 0)
{
var addcomma = false;
for (int i = 0; i < CurrentFaultFlags.Count; i++)
{
if (addcomma) sb.AppendFormat(", ");
addcomma = true;
sb.AppendFormat("{0}", CurrentFaultFlags[i].ToString());
}
}
else
{
sb.AppendFormat("none");
}
lines.Add(new List<string>() { sb.ToString() });
sb = new StringBuilder();
sb.AppendFormat("Extended Fault Flags: ");
if (null != ExtendedFaultFlags && ExtendedFaultFlags.Count > 0)
{
var addcomma = false;
for (int i = 0; i < ExtendedFaultFlags.Count; i++)
{
if (addcomma) sb.AppendFormat(", ");
addcomma = true;
sb.AppendFormat("{0}", ExtendedFaultFlags[i].ToString());
}
}
else
{
sb.AppendFormat("none");
}
lines.Add(new List<string>() { sb.ToString() });
}
}
public class Disarm : ArmCommands
{
protected override Commands _Command => Commands.Disarm;
public Disarm(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public Disarm(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class PrepareForDiagnostics : ArmCommands
{
protected override Commands _Command => Commands.PrepareForDiagnostics;
public PrepareForDiagnostics(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public PrepareForDiagnostics(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class PrepareForDataCollection : ArmCommands
{
protected override Commands _Command => Commands.PrepareForDataCollection;
public PrepareForDataCollection(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public PrepareForDataCollection(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class BeginFlashErase : ArmCommands
{
protected override Commands _Command => Commands.BeginFlashErase;
public BeginFlashErase(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public BeginFlashErase(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class QueryFlashEraseStatus : ArmCommands
{
protected override Commands _Command => Commands.QueryFlashEraseStatus;
public QueryFlashEraseStatus(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryFlashEraseStatus(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
private float _percentcomplete;
public float PercentComplete => _percentcomplete;
private byte _lasterror;
public DFConstantsAndEnums.CommandStatus LastError => (DFConstantsAndEnums.CommandStatus)_lasterror;
protected override CommandReceiveAction WholePackage()
{
const int LastErrorPosition = 0;
const int PercentCompletePosition = 1;
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(LastErrorPosition, out _lasterror);
response.GetParameter(PercentCompletePosition, out _percentcomplete);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"Erase status: {LastError.ToString()}, Percent complete: {PercentComplete.ToString()}" });
}
}
public class InitializeHardwareLines : ArmCommands
{
protected override Commands _Command => Commands.InitializeHardwareLines;
public bool CheckTriggerForShort
{
get => Convert.ToBoolean(command.Parameter[0]);
set => command.Parameter[0] = Convert.ToByte(value);
}
public bool CheckStartForShort
{
get => Convert.ToBoolean(command.Parameter[1]);
set => command.Parameter[1] = Convert.ToByte(value);
}
public InitializeHardwareLines(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[] { 0x01, 0x01 };
LogCommands = false;
}
public InitializeHardwareLines(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[] { 0x01, 0x01 };
LogCommands = false;
}
public bool StartRecordShorted { get; private set; } = false;
public bool TriggerInputShorted { get; private set; } = false;
protected override CommandReceiveAction WholePackage()
{
switch (response.Status)
{
case DFConstantsAndEnums.CommandStatus.StatusNoError:
break;
case DFConstantsAndEnums.CommandStatus.StatusArmShortedStartRecordInput:
StartRecordShorted = true;
break;
case DFConstantsAndEnums.CommandStatus.StatusArmShortedTriggerInput:
TriggerInputShorted = true;
break;
case DFConstantsAndEnums.CommandStatus.StatusArmShortedStartAndTrigger:
StartRecordShorted = true;
TriggerInputShorted = true;
break;
default:
APILogger.Log("Unexpected return from InitializeHardwareLines ", response.Status.ToString());
break;
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>(new[] { $"StartRecord: {StartRecordShorted}, Trigger: {TriggerInputShorted}" }));
}
public static void Log(Exception exception, InitializeHardwareLines ihl)
{
var bShortStart = exception.Message.Contains(DFConstantsAndEnums.CommandStatus.StatusArmShortedStartRecordInput.ToString());
var bShortTrig = exception.Message.Contains(DFConstantsAndEnums.CommandStatus.StatusArmShortedTriggerInput.ToString());
if (exception.Message.Contains(DFConstantsAndEnums.CommandStatus.StatusArmShortedStartAndTrigger.ToString()))
{
bShortStart = true;
bShortTrig = true;
}
APILogger.Log($"InitializeHardwareLines: Start shorted: {bShortStart} Trigger shorted: {bShortTrig}");
}
}
}

View File

@@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using DTS.Common.DASResource;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class QueryEventDataBase : EventDataCommands
{
protected override Commands Command => Commands.QueryEventData;
private const ushort ADC_OFFSET = 0x8000;
public const byte ALL_CHANNELS = 0xFF;
protected UInt16 _eventNumber;
protected UInt64 _firstSample;
protected UInt64 _lastSample;
protected UInt64 _samplesDownloaded;
protected byte _channel;
protected int _channelsDownloaded;
protected ushort[] _data;
public UInt16 EventNumber
{
get => _eventNumber;
set { _eventNumber = value; command.SetParameter(0, _eventNumber); }
}
public virtual UInt64 FirstSample
{
get => _firstSample;
set { _firstSample = value; command.SetParameter(2, _firstSample); }
}
public virtual UInt64 LastSample
{
get => _lastSample;
set { _lastSample = value; command.SetParameter(10, _lastSample); }
}
public byte Channel
{
get => _channel;
set
{
_channel = value; command.SetParameter(18, _channel);
ChannelsDownloaded = 0xFF == _channel ? 3 : 1;
}
}
public int ChannelsDownloaded
{
get => _channelsDownloaded;
set => _channelsDownloaded = value;
}
public int Count => (int)_samplesDownloaded;
public QueryEventDataBase(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[19];
_data = null;
_eventNumber = 0;
_firstSample = 0;
_lastSample = 0;
_channel = 0;
command.ShouldLog = false;
}
public QueryEventDataBase(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Parameter = new byte[19];
_data = null;
_eventNumber = 0;
_firstSample = 0;
_lastSample = 0;
_channel = 0;
command.ShouldLog = false;
}
public override void Execute(CommandCallback cb, object cbData)
{
// Do a little parameter checking
if (_firstSample > _lastSample)
{
// "QueryEventData.Execute: First Sample cannot be greater than Last Sample"
throw new ApplicationException(Strings.QueryEventData_Execute_Err1);
}
base.Execute(cb, cbData);
}
protected override CommandReceiveAction WholePackagePost()
{
// now send the data to the user
var stat = CommandStatus.Success;
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
var s = (int)response.Status;
APILogger.LogString("QueryEventData.WholePackagePost: reporting failure, status==" + CommandPacketBase.StatusLabels[s] + " (0x" + s.ToString("X") + ")");
stat = CommandStatus.Failure;
}
var cbReport = new QueryEventDataReport(stat, UserCallbackData);
cbReport.Data = new short[_channelsDownloaded][];
for (var i = 0; i < _channelsDownloaded; i++)
GetChannelData(i, out cbReport.Data[i]);
return UserCallback(cbReport);
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
return CommandReceiveAction.StopReceiving;
}
_samplesDownloaded = (ulong)(response.Parameter.Length / 2) / (ulong)_channelsDownloaded;
_data = new ushort[_samplesDownloaded * (ulong)_channelsDownloaded];
for (var i = 0; (ulong)i < _samplesDownloaded * (ulong)_channelsDownloaded; i++)
{
response.GetParameter(2 * i, out _data[i]);
}
return CommandReceiveAction.StopReceiving;
}
public override void SyncExecute()
{
// Do a little parameter checking
if (_firstSample > _lastSample)
{
// "QueryEventData.SyncExecute: First Sample cannot be greater than Last Sample"
throw new ApplicationException(Strings.QueryEventData_SyncExecute_Err1);
}
base.SyncExecute();
}
public virtual void GetChannelData(int channel, out short[] signedADC)
{
if (channel < 0 || channel > _channelsDownloaded)
{
// "QueryEventData.GetChannelData: Data requested on a channel that wasn't downloaded."
throw new ApplicationException(Strings.QueryEventData_GetChannelData_Err1);
}
// Data order for a 9 channel stack
// 7 8 9 4 5 6 1 2 3 7 8 9 4 5 6 1 2 3 etc.
var rv = new short[_samplesDownloaded];
var sliceNumber = channel / 3;
var sliceOffset = (_channelsDownloaded / 3 - sliceNumber - 1) * 3;
if (sliceOffset < 0) sliceOffset = 0;
var channelInSlice = channel % 3;
for (var i = 0; i < rv.Length; i++)
{
rv[i] = (short)(_data[i * _channelsDownloaded + sliceOffset + channelInSlice] - ADC_OFFSET);
}
signedADC = rv;
}
public virtual void GetRawIndexedData(int index, out ushort[] data)
{
data = new ushort[_samplesDownloaded];
for (var i = 0; i < data.Length; i++)
{
data[i] = _data[i * _channelsDownloaded + index];
}
}
public override void CommandToString(ref List<List<string>> lines)
{
lines.Add(new List<string> { $"Event number: {EventNumber}, First sample: {FirstSample}, Last sample: {LastSample}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
lines.Add(new List<string>
{
$"ChannelsDownloaded: {ChannelsDownloaded}, Count: {Count}"
});
}
public void LogResponse()
{
LogCommand(false);
}
}
}

View File

@@ -0,0 +1,32 @@
// ReSharper disable once InconsistentNaming
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MACTableEntry
{
public ushort Age { get; }
public ushort Port { get; }
public ushort Filter { get; }
// ReSharper disable once InconsistentNaming
public byte[] MAC { get; }
public MACTableEntry(ushort age, ushort port, ushort filter, byte[] mac)
{
Age = age;
Port = port;
Filter = filter;
MAC = mac;
}
}
public class DiscoveredConnectedSlice
{
public string DeviceMAC { get; }
public MACTableEntry[] ConnectedDevices { get; }
public DiscoveredConnectedSlice(string deviceMAC, MACTableEntry[] devices)
{
DeviceMAC = deviceMAC;
ConnectedDevices = devices;
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
using DTS.DASLib.Communication;
using DTS.DASLib.Utility;
namespace DTS.DASLib.Command.SLICE
{
public abstract class Commands_Stack_Setup: CommandBase
{
protected enum Commands
{
};
protected Commands_Stack_Setup(ICommunication sock)
: base(sock)
{
this.command.Type = CommandPacket.CommandType.StackSetup;
}
protected Commands_Stack_Setup(ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
this.command.Type = CommandPacket.CommandType.StackSetup;
}
}
}

View File

@@ -0,0 +1,91 @@
using DTS.Common.ICommunication;
using System.Collections.Generic;
namespace DTS.DASLib.Command.SLICE.RealtimeCommands
{
public class StartTimeStampStreamMode : RealtimeCommandBase
{
private bool _bSupportsIrigTimeStampSampleRealtime = true;
public bool SupportsMultipleSampleRealtime
{
get { return _bSupportsIrigTimeStampSampleRealtime; }
set
{
_bSupportsIrigTimeStampSampleRealtime = value;
if (value) { command.Parameter = new byte[1]; }
else { command.Parameter = new byte[0]; }
}
}
protected override Commands _Command => Commands.StartTimeStampStreamMode;
public StartTimeStampStreamMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(Common.Enums.DASFactory.DFConstantsAndEnums.ProtocolLimitedCommands.UDPRealtimeStream);
}
public StartTimeStampStreamMode(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
MinimumProtocolVersion = sock.GetMinProto(Common.Enums.DASFactory.DFConstantsAndEnums.ProtocolLimitedCommands.UDPRealtimeStream);
}
private byte[] _paramsToSend;
public byte[] ParamsToSend
{
get => _paramsToSend;
set
{
_paramsToSend = value;
command.Parameter = new byte[value.Length];
for (var i = 0; i < value.Length; i++)
{
command.SetParameter(i, _paramsToSend[i]);
}
}
}
public override void CommandToString(ref List<List<string>> list)
{
base.CommandToString(ref list);
list.Add(new List<string>(new[] { $"ParamsToSend: {System.Text.Encoding.UTF8.GetString(ParamsToSend)}" }));
}
}
/// <summary>
/// this puts the firmware into realtime streaming mode
/// in this mode the firmware will constantly send out realtime data
/// </summary>
public class StartRealtimeStreamingMode : RealtimeCommandBase
{
protected override Commands _Command => Commands.StartRealtimeStreamingMode;
public StartRealtimeStreamingMode(DTS.Common.Interface.DASFactory.ICommunication sock, byte[] channelList)
: base(sock)
{
ChannelList = channelList;
}
public StartRealtimeStreamingMode(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec, byte[] channelList)
: base(sock, timeoutMillisec)
{
ChannelList = channelList;
}
private byte[] _channelList;
/// <summary>
/// channels to collect data on, each channel should be represented as a byte
/// </summary>
public byte[] ChannelList
{
get => _channelList;
set
{
_channelList = value;
command.Parameter = new byte[value.Length];
for (var i = 0; i < value.Length; i++)
{
command.SetParameter(i, value[i]);
}
}
}
}
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastSetDhcp : MulticastCommandBase
{
const int COMMAND_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE + 1;
protected override Commands Command => Commands.SetDhcp;
private byte _dhcp;
public bool Dhcp
{
set
{
_dhcp = Convert.ToByte(value);
command.SetParameter(FIRST_PARAMETER_OFFSET, _dhcp);
}
}
public MulticastSetDhcp(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public MulticastSetDhcp(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} DHCP: {_dhcp} " });
}
}
}

View File

@@ -0,0 +1,45 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class QueryTotalEventCount : EventDataCommands
{
protected override Commands Command => Commands.QueryTotalEventCount;
private ushort _count;
public ushort Count => _count;
public QueryTotalEventCount(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryTotalEventCount(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
if (response.ParameterLength > 0)
{
response.GetParameter(0, out _count);
}
else { _count = 0; }
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>
{
$"Count: {Count}"
});
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace DTS.DASLib.Command.SLICE
{
public class CommandPacket : SliceCommandPacketBase
{
public enum CommandType
{
Reserved = 0,
Arm = 1,
Attribute = 2,
Diagnostics = 3,
EventData = 4,
FirmwareUpdate = 5,
Information = 6,
QAandUtility = 7,
Realtime = 8,
Bulk = 9,
StackFirmwareUpdate = 10,
Ptp1588 = 11,
Multicast = 12,
};
private static UInt16 GlobalSequenceNumber = 0;
private static object GlobalSequenceNumberLock = new object();
public CommandPacket() : base() { }
public override void GetNextSequenceNumber()
{
lock (GlobalSequenceNumberLock)
{
SequenceNumber = GlobalSequenceNumber;
GlobalSequenceNumber++;
}
}
public CommandPacket(byte[] Bytes) : base(Bytes) { }
public override object ConvertByteToCommandType(byte b)
{
return (CommandType)b;
}
}
}

View File

@@ -0,0 +1,41 @@
using System.Collections.Generic;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastSetDnsAddress : MulticastCommandBase
{
private const int COMMAND_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE + IP_ADDR_SIZE;
protected override Commands Command => Commands.SetDnsAddress;
private string _dns;
public string Dns
{
set
{
_dns = value;
command.SetParameter(FIRST_PARAMETER_OFFSET, _dns);
}
}
public MulticastSetDnsAddress(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public MulticastSetDnsAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} DNS: {_dns}" });
}
}
}

View File

@@ -0,0 +1,19 @@
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class ResetEventList : EventDataCommands
{
protected override Commands Command => Commands.ResetEventList;
public ResetEventList(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public ResetEventList(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
}
}

Binary file not shown.

View File

View File

@@ -0,0 +1,643 @@
using System;
using System.Collections.Generic;
using System.Text;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Command.SLICE
{
public abstract class ArmCommands : CommandBase
{
protected enum Commands
{
Reserved = 0x00,
Arm = 0x01,
Disarm = 0x02,
EnableFaultChecking = 0x03,
DisableFaultChecking = 0x04,
QueryArmAndTriggerStatus = 0x05,
PrepareForDiagnostics = 0x06,
PrepareForDataCollection = 0x07,
BeginFlashErase = 0x08,
QueryFlashEraseStatus = 0x09,
InitializeHardwareLines = 0x0a,
};
protected abstract Commands _Command { get; }
protected ArmCommands(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.Arm;
command.SetCommand((byte)_Command, _Command.ToString());
}
protected ArmCommands(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Type = CommandPacket.CommandType.Arm;
command.SetCommand((byte)_Command, _Command.ToString());
}
}
public class Arm : ArmCommands
{
protected override Commands _Command => Commands.Arm;
public Arm(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public Arm(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
public DFConstantsAndEnums.CommandStatus ArmStatus { get; private set; } = DFConstantsAndEnums.CommandStatus.StatusNoError;
protected override CommandReceiveAction WholePackage()
{
switch (response.Status)
{
case DFConstantsAndEnums.CommandStatus.StatusNoError:
break;
default:
ArmStatus = response.Status;
break;
}
return CommandReceiveAction.StopReceiving;
}
}
public class EnableFaultChecking : ArmCommands
{
protected override Commands _Command => Commands.EnableFaultChecking;
public EnableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public EnableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class DisableFaultChecking : ArmCommands
{
protected override Commands _Command => Commands.DisableFaultChecking;
public DisableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public DisableFaultChecking(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class QueryArmAndTriggerStatus : ArmCommands
{
protected override Commands _Command => Commands.QueryArmAndTriggerStatus;
public enum FaultFlags
{
IncomingStatusLineDropped = (1 << 0),
ADCBufferOverrun = (1 << 1),
FlashCRCError = (1 << 2),
TriggerBeforeStart = (1 << 3),
InputVoltageLow = (1 << 4),
InputVoltageHigh = (1 << 5),
BackupVoltageLow = (1 << 6),
BackupVoltageHigh = (1 << 7),
OutOfMemory = (1 << 8),
SquibResistanceOutOfRange = (1 << 9),
SafeSwitchUnplugged = (1 << 10),
SquibPowerOutOfRange = (1 << 11),
AutoSquibDisableActivated = (1 << 12)
}
private float _inputVoltage = 0;
public float InputVoltage => _inputVoltage;
private float _backupVoltage = 0;
public float BackupVoltage => _backupVoltage;
private byte _armstate;
private byte _armmode;
private byte _startrecordstatus;
private byte _triggerstatus;
private byte _faultstatus;
private uint _eventsamplerate;
private ulong _totalsamples;
private ulong _currentsample;
private ushort _currenteventnumber;
private ulong _faultsamplenumber;
private ushort _faultbits;
private float _batterySoc;
private float _systemTempC;
private ulong _actualCurrentSample;
private ulong _maxSampleAvailable;
private short _tsChannel1;
private short _tsChannel2;
private short _tsChannel3;
private short _sensorChannelA;
private short _sensorChannelB;
private short _sensorChannelC;
private short _sensorChannelD;
private short _sensorChannelE;
private short _sensorChannelF;
// for TOM
private float _squib1;
private float _squib2;
private float _squib3;
private float _squib4;
private float _squibP17V;
private float _squibP5V;
private float _squibP3p3V;
private float _squibN5V;
private bool _ptpEnable;
private bool _adcPtpClkEnable;
private bool _ptpSyncStatus;
private bool _adcClkSyncStatus;
private uint _extFaultId;
public ArmStates ArmState => (ArmStates)_armstate;
public enum ArmStates { Disarmed, Armed, Realtime, Diagnostics, FlashClear, Arming };
public byte ArmMode => _armmode;
public bool IsDiagnostics => (ArmStates)_armstate == ArmStates.Diagnostics;
public bool IsFlashClear => (ArmStates)_armstate == ArmStates.FlashClear;
public bool IsArming => (ArmStates)_armstate == ArmStates.Arming;
public bool IsArmed => (ArmStates)_armstate == ArmStates.Armed;
public bool IsInRealtime => (ArmStates)_armstate == ArmStates.Realtime;
public bool IsRecording => _startrecordstatus == 0x01;
public bool IsTriggered => _triggerstatus == 0x01;
public bool IsFaulted => _faultstatus == 0x01;
public uint EventSampleRate => _eventsamplerate;
public ulong TotalSamples => _totalsamples;
public ulong CurrentSample => _currentsample;
public ushort EventNumber => _currenteventnumber;
public ulong FaultSampleNumber => _faultsamplenumber;
public List<FaultFlags> CurrentFaultFlags { get; } = new List<FaultFlags>();
public int BatterySoc => (int)_batterySoc;
public float SystemTempC => _systemTempC;
public ulong ActualCurrentSample => _actualCurrentSample;
public ulong MaxSampleAvailable => _maxSampleAvailable;
public short TiltSensorChannel1 => _tsChannel1;
public short TiltSensorChannel2 => _tsChannel2;
public short TiltSensorChannel3 => _tsChannel3;
public short SensorChannelA => _sensorChannelA;
public short SensorChannelB => _sensorChannelB;
public short SensorChannelC => _sensorChannelC;
public short SensorChannelD => _sensorChannelD;
public short SensorChannelE => _sensorChannelE;
public short SensorChannelF => _sensorChannelF;
public float SquibResistance1 { get { return _squib1; } }
public float SquibResistance2 { get { return _squib2; } }
public float SquibResistance3 { get { return _squib3; } }
public float SquibResistance4 { get { return _squib4; } }
public float SquibPowerP17V { get { return _squibP17V; } }
public float SquibPowerP5V { get { return _squibP5V; } }
public float SquibPowerP3p3V { get { return _squibP3p3V; } }
public float SquibPowerN5V { get { return _squibN5V; } }
public bool PtpFunctionEnable { get { return _ptpEnable; } }
public bool AdcPtpClkEnable { get { return _adcPtpClkEnable; } }
public bool PtpClkSyncStatus { get { return _ptpSyncStatus; } }
public bool AdcClkSyncStatus { get { return _adcClkSyncStatus; } }
private List<QATSExtendedFault> _extendedFaultFlags = new List<QATSExtendedFault>();
public List<QATSExtendedFault> ExtendedFaultFlags { get { return _extendedFaultFlags; } }
public uint ExtendedFaultId { get { return _extFaultId; } }
public QueryArmAndTriggerStatus(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryArmAndTriggerStatus(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
private const int QUATS_MIN_LENGTH_INPUTVOLTAGE = 38;
private const int QUATS_MIN_LENGTH_BACKUPVOLTAGE = 42;
private const int QUATS_MIN_LENGTH_BATTERYSOC = 49;
private const int QUATS_MIN_LENGTH_ACTUALCURRENTSAMPLE = 57;
private const int QUATS_MIN_LENGTH_MAXSAMPLEAVAILABLE = 65;
private const int QUATS_MIN_LENGTH_TILTCHANNELDATA = 71;
private const int QUATS_MIN_LENGTH_SYSTEMTEMP = 75;
private const int QUATS_MIN_LENGTH_CHANNELADC = 87;
private const int QUATS_MIN_LENGTH_TOMSTATUS = 119;
private const int QUATS_MIN_LENGTH_CLKSTATUS = 123;
private const int QUATS_MIN_LENGTH_EXTFAULTID = 127;
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
if (response.ParameterLength > 1)
{
response.GetParameter(0, out _armstate);
response.GetParameter(1, out _armmode);
response.GetParameter(2, out _startrecordstatus);
response.GetParameter(3, out _triggerstatus);
response.GetParameter(4, out _faultstatus);
response.GetParameter(5, out _eventsamplerate);
response.GetParameter(9, out _totalsamples);
response.GetParameter(17, out _currentsample);
response.GetParameter(25, out _currenteventnumber);
response.GetParameter(27, out _faultsamplenumber);
//this is only valid for > 00E7, but that's long retired, so I'm enforcing it now
response.GetParameter(35, out _faultbits);
for (int i = 0; i < 16; i++)
{
if (0 != (_faultbits & (1 << i)))
{
CurrentFaultFlags.Add((FaultFlags)(1 << i));
}
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_INPUTVOLTAGE)
{
response.GetParameter(37, out _inputVoltage);
}
else
{
_inputVoltage = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_BACKUPVOLTAGE)
{
response.GetParameter(41, out _backupVoltage);
}
else
{
_backupVoltage = 0;
}
if (recorder.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.QueryBatterySOC)
&& response.ParameterLength >= QUATS_MIN_LENGTH_BATTERYSOC)
{
response.GetParameter(45, out _batterySoc);
}
else
{
_batterySoc = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_ACTUALCURRENTSAMPLE)
{
response.GetParameter(49, out _actualCurrentSample);
}
else
{
_actualCurrentSample = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_MAXSAMPLEAVAILABLE)
{
response.GetParameter(57, out _maxSampleAvailable);
}
else
{
_maxSampleAvailable = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_TILTCHANNELDATA)
{
response.GetParameter(65, out _tsChannel1);
response.GetParameter(67, out _tsChannel2);
response.GetParameter(69, out _tsChannel3);
}
else
{
_tsChannel1 = 0;
_tsChannel2 = 0;
_tsChannel3 = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_SYSTEMTEMP)
{
response.GetParameter(71, out _systemTempC);
}
else
{
_systemTempC = 0;
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_CHANNELADC)
{
response.GetParameter(75, out _sensorChannelA);
response.GetParameter(77, out _sensorChannelB);
response.GetParameter(79, out _sensorChannelC);
response.GetParameter(81, out _sensorChannelD);
response.GetParameter(83, out _sensorChannelE);
response.GetParameter(85, out _sensorChannelF);
}
else
{
_sensorChannelA = 0;
_sensorChannelB = 0;
_sensorChannelC = 0;
_sensorChannelD = 0;
_sensorChannelE = 0;
_sensorChannelF = 0;
}
// hack for TOM
if (response.ParameterLength >= QUATS_MIN_LENGTH_TOMSTATUS)
{
response.GetParameter(87, out _squib1);
response.GetParameter(91, out _squib2);
response.GetParameter(95, out _squib3);
response.GetParameter(99, out _squib4);
response.GetParameter(103, out _squibP17V);
response.GetParameter(107, out _squibP5V);
response.GetParameter(111, out _squibP3p3V);
response.GetParameter(115, out _squibN5V);
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_CLKSTATUS)
{
response.GetParameter(119, out _ptpEnable);
response.GetParameter(120, out _adcPtpClkEnable);
response.GetParameter(121, out _ptpSyncStatus);
response.GetParameter(122, out _adcClkSyncStatus);
}
if (response.ParameterLength >= QUATS_MIN_LENGTH_EXTFAULTID)
{
response.GetParameter(123, out _extFaultId);
}
for (int i = 0; i < 32; i++)
{
if (0 != (_extFaultId & (1 << i)))
{
_extendedFaultFlags.Add((QATSExtendedFault)(1 << i));
}
}
}
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"Event number: {EventNumber}, Arm Mode: {ArmMode}" });
lines.Add(new List<string>() { $"Armed: {IsArmed}, Started: {IsRecording}, Triggered: {IsTriggered}, Faulted: {IsFaulted}, Diagnostics: {IsDiagnostics}, FlashClear: {IsFlashClear}, Arming: {IsArming}, ArmState: {_armstate}" });
lines.Add(new List<string>() { $"Samplerate: {EventSampleRate}, Current Sample: {CurrentSample}, Total Samples: {TotalSamples}, Fault Sample Number: {FaultSampleNumber}" });
lines.Add(new List<string>() { $"Input Voltage: {InputVoltage.ToString("N3")}V, Backup Voltage: {BackupVoltage.ToString("N3")}V, Backup Percentage Remaining: {BatterySoc}%" });
lines.Add(new List<string>() { $"System Temp: {SystemTempC}C, Actual Current Sample: {ActualCurrentSample}, Max Sample Available: {MaxSampleAvailable}" });
lines.Add(new List<string>() { $"Tilt Ch1: {TiltSensorChannel1}, Tilt Ch2: {TiltSensorChannel2}, Tilt Ch3: {TiltSensorChannel3}" });
lines.Add(new List<string>() { $"Squib Ch1: {SquibResistance1}, Squib Ch2: { SquibResistance2}, Squib Ch3: { SquibResistance3}, Squib Ch4: { SquibResistance4}" });
lines.Add(new List<string>() { $"Squib P17V: {SquibPowerP17V}, Squib PV5: { SquibPowerP5V}, Squib P3p3V: { SquibPowerP3p3V}, Squib N5V: { SquibPowerN5V}" });
lines.Add(new List<string>() { $"PTP Enabled: {PtpFunctionEnable}, PTP Clk Enable: {AdcPtpClkEnable}, PTP Clk Sync Status: {PtpClkSyncStatus}, ADC Clk Sync Status: {AdcClkSyncStatus}" });
var sb = new StringBuilder(50);
sb.AppendFormat("Fault Flags: ");
if (null != CurrentFaultFlags && CurrentFaultFlags.Count > 0)
{
var addcomma = false;
for (int i = 0; i < CurrentFaultFlags.Count; i++)
{
if (addcomma) sb.AppendFormat(", ");
addcomma = true;
sb.AppendFormat("{0}", CurrentFaultFlags[i].ToString());
}
}
else
{
sb.AppendFormat("none");
}
lines.Add(new List<string>() { sb.ToString() });
sb = new StringBuilder();
sb.AppendFormat("Extended Fault Flags: ");
if (null != ExtendedFaultFlags && ExtendedFaultFlags.Count > 0)
{
var addcomma = false;
for (int i = 0; i < ExtendedFaultFlags.Count; i++)
{
if (addcomma) sb.AppendFormat(", ");
addcomma = true;
sb.AppendFormat("{0}", ExtendedFaultFlags[i].ToString());
}
}
else
{
sb.AppendFormat("none");
}
lines.Add(new List<string>() { sb.ToString() });
}
}
public class Disarm : ArmCommands
{
protected override Commands _Command => Commands.Disarm;
public Disarm(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public Disarm(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class PrepareForDiagnostics : ArmCommands
{
protected override Commands _Command => Commands.PrepareForDiagnostics;
public PrepareForDiagnostics(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public PrepareForDiagnostics(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class PrepareForDataCollection : ArmCommands
{
protected override Commands _Command => Commands.PrepareForDataCollection;
public PrepareForDataCollection(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public PrepareForDataCollection(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class BeginFlashErase : ArmCommands
{
protected override Commands _Command => Commands.BeginFlashErase;
public BeginFlashErase(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public BeginFlashErase(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class QueryFlashEraseStatus : ArmCommands
{
protected override Commands _Command => Commands.QueryFlashEraseStatus;
public QueryFlashEraseStatus(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryFlashEraseStatus(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
private float _percentcomplete;
public float PercentComplete => _percentcomplete;
private byte _lasterror;
public DFConstantsAndEnums.CommandStatus LastError => (DFConstantsAndEnums.CommandStatus)_lasterror;
protected override CommandReceiveAction WholePackage()
{
const int LastErrorPosition = 0;
const int PercentCompletePosition = 1;
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(LastErrorPosition, out _lasterror);
response.GetParameter(PercentCompletePosition, out _percentcomplete);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"Erase status: {LastError.ToString()}, Percent complete: {PercentComplete.ToString()}" });
}
}
public class InitializeHardwareLines : ArmCommands
{
protected override Commands _Command => Commands.InitializeHardwareLines;
public bool CheckTriggerForShort
{
get => Convert.ToBoolean(command.Parameter[0]);
set => command.Parameter[0] = Convert.ToByte(value);
}
public bool CheckStartForShort
{
get => Convert.ToBoolean(command.Parameter[1]);
set => command.Parameter[1] = Convert.ToByte(value);
}
public InitializeHardwareLines(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[] { 0x01, 0x01 };
LogCommands = false;
}
public InitializeHardwareLines(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[] { 0x01, 0x01 };
LogCommands = false;
}
public bool StartRecordShorted { get; private set; } = false;
public bool TriggerInputShorted { get; private set; } = false;
protected override CommandReceiveAction WholePackage()
{
switch (response.Status)
{
case DFConstantsAndEnums.CommandStatus.StatusNoError:
break;
case DFConstantsAndEnums.CommandStatus.StatusArmShortedStartRecordInput:
StartRecordShorted = true;
break;
case DFConstantsAndEnums.CommandStatus.StatusArmShortedTriggerInput:
TriggerInputShorted = true;
break;
case DFConstantsAndEnums.CommandStatus.StatusArmShortedStartAndTrigger:
StartRecordShorted = true;
TriggerInputShorted = true;
break;
default:
APILogger.Log("Unexpected return from InitializeHardwareLines ", response.Status.ToString());
break;
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>(new[] { $"StartRecord: {StartRecordShorted}, Trigger: {TriggerInputShorted}" }));
}
public static void Log(Exception exception, InitializeHardwareLines ihl)
{
var bShortStart = exception.Message.Contains(DFConstantsAndEnums.CommandStatus.StatusArmShortedStartRecordInput.ToString());
var bShortTrig = exception.Message.Contains(DFConstantsAndEnums.CommandStatus.StatusArmShortedTriggerInput.ToString());
if (exception.Message.Contains(DFConstantsAndEnums.CommandStatus.StatusArmShortedStartAndTrigger.ToString()))
{
bShortStart = true;
bShortTrig = true;
}
APILogger.Log($"InitializeHardwareLines: Start shorted: {bShortStart} Trigger shorted: {bShortTrig}");
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Reflection;
using System.IO;
using System.Diagnostics;
using DTS.Common.ICommunication;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Command.SLICE
{
public abstract class CommandBase : SliceCommandBase
{
public CommandBase(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock)
{
command = new CommandPacket();
}
public CommandBase(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec)
{
command = new CommandPacket();
}
protected override CommandPacketBase GetCommandPacket()
{
return new CommandPacket();
}
protected override CommandPacketBase GetCommandPacket(byte[] buffer)
{
return new CommandPacket(buffer);
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace DTS.DASLib.Command.SLICE
{
public class CommandPacket : SliceCommandPacketBase
{
public enum CommandType
{
Reserved = 0,
Arm = 1,
Attribute = 2,
Diagnostics = 3,
EventData = 4,
FirmwareUpdate = 5,
Information = 6,
QAandUtility = 7,
Realtime = 8,
Bulk = 9,
StackFirmwareUpdate = 10,
Ptp1588 = 11,
Multicast = 12,
};
private static UInt16 GlobalSequenceNumber = 0;
private static object GlobalSequenceNumberLock = new object();
public CommandPacket() : base() { }
public override void GetNextSequenceNumber()
{
lock (GlobalSequenceNumberLock)
{
SequenceNumber = GlobalSequenceNumber;
GlobalSequenceNumber++;
}
}
public CommandPacket(byte[] Bytes) : base(Bytes) { }
public override object ConvertByteToCommandType(byte b)
{
return (CommandType)b;
}
}
}

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.DownloadByteConverter" Collapsed="true">
<Position X="2.25" Y="4" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAQAAAAAAAIREAAAAAQAAgAAAQAgAAAgQAAA=</HashCode>
<FileName>DownloadCommands\DownloadByteConverter.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.EventDataCommands" Collapsed="true">
<Position X="5" Y="0.5" Width="2" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>DownloadCommands\EventDataCommands.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.GetNextDownloadStreamDataSamples" Collapsed="true">
<Position X="7.25" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>EgAAAAAAAAAAAAAAAAAABAQAAAABgAAAAAAAAAAAAAA=</HashCode>
<FileName>DownloadCommands\GetNextDownloadStreamDataSamples.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.QueryEventDataBase" Collapsed="true">
<Position X="0.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AkAAAAAghABIAAQBAIAABIRCAAAAAAgAAABAFFEgAEA=</HashCode>
<FileName>DownloadCommands\QueryEventDataBase.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.QueryEventDataReport" Collapsed="true">
<Position X="4" Y="4" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAEAAAAAAAAAAAAAAAAAAAAABAAAAAAAIAAAAA=</HashCode>
<FileName>DownloadCommands\QueryEventDataReport.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.QueryTotalEventCount" Collapsed="true">
<Position X="9.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABAQAAAAAAAAAAACAAEAAAEA=</HashCode>
<FileName>DownloadCommands\QueryTotalEventCount.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.ResetEventList" Collapsed="true">
<Position X="2.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>DownloadCommands\ResetEventList.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.DownloadCommands.StartDownloadStreamData" Collapsed="true">
<Position X="5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAgAAAAAABAAAABAAAAAAAAAoAAABAABAgAAA=</HashCode>
<FileName>DownloadCommands\StartDownloadStreamData.cs</FileName>
</TypeIdentifier>
</Class>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MACTableEntry" Collapsed="true">
<Position X="8.25" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAABAAAAAAAAAAAEAAAAAACBAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MACTableEntry.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.DiscoveredConnectedSlice" Collapsed="true">
<Position X="6.5" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAACAAAAAAA=</HashCode>
<FileName>MulticastCommands\MACTableEntry.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastAutoDiscover" Collapsed="true">
<Position X="14" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>EAAACUEAAAIAIAgIAEBAFABACAgRgAACQCQACWAAABA=</HashCode>
<FileName>MulticastCommands\MulticastAutoDiscover.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastCommandBase" Collapsed="true">
<Position X="15.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>IAACgAAJEABAAAAAIIAEBggQwAAAwCAAFAEIgsgQAAA=</HashCode>
<FileName>MulticastCommands\MulticastCommandBase.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastDiscoverSlice6" Collapsed="true">
<Position X="25.25" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>QAIACQAAACMKAAAAABAABARAAAgTiAAAQAAQIWAAQEA=</HashCode>
<FileName>MulticastCommands\MulticastDiscoverSlice6.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastGetDhcp" Collapsed="true">
<Position X="0.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAAABABAAAAAAAAAAAAAAEAAAEA=</HashCode>
<FileName>MulticastCommands\MulticastGetDhcp.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastGetDnsAddress" Collapsed="true">
<Position X="7.25" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEAAAAAAAAAAAAAAEAABABAAAAAAAAAAAAAAEAAAEA=</HashCode>
<FileName>MulticastCommands\MulticastGetDnsAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastGetGatewayAddress" Collapsed="true">
<Position X="16.25" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAACAAAAAAAAAAAAAAAJABAAAAAAAAAAAAAAEAAAEA=</HashCode>
<FileName>MulticastCommands\MulticastGetGatewayAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastGetIpAddress" Collapsed="true">
<Position X="20.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAABABABAAAAAAAAAAAAAAEAAIEA=</HashCode>
<FileName>MulticastCommands\MulticastGetIpAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastGetSubnetAddress" Collapsed="true">
<Position X="27.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABABAAAAAAACAAAAAAEAAAFA=</HashCode>
<FileName>MulticastCommands\MulticastGetSubnetAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastIdentify" Collapsed="true">
<Position X="2.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABABAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MulticastIdentify.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastResetMcu" Collapsed="true">
<Position X="9.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABABAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MulticastResetMcu.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastSetDhcp" Collapsed="true">
<Position X="18.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAAABABAAAAAAAAAQAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MulticastSetDhcp.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastSetDnsAddress" Collapsed="true">
<Position X="23" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEAAAAAAAAAAAAAAEAABABAAAAAAAAAQAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MulticastSetDnsAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastSetGatewayAddress" Collapsed="true">
<Position X="29.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAACAAAAAAAAAAAAAAAJABAAAAAAAAAQAAAAAAAAAA=</HashCode>
<FileName>MulticastCommands\MulticastSetGatewayAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastSetIpAddress" Collapsed="true">
<Position X="5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAABABABAAAAAAAAAQAAAAAAAIAA=</HashCode>
<FileName>MulticastCommands\MulticastSetIPAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.MulticastCommands.MulticastSetSubnetAddress" Collapsed="true">
<Position X="11.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABABAAAAAAACAQAAAAAAAABA=</HashCode>
<FileName>MulticastCommands\MulticastSetSubnetAddress.cs</FileName>
</TypeIdentifier>
</Class>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.EndRealtimeMode" Collapsed="true">
<Position X="0.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>RealtimeCommands\EndRealtimeMode.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.GetRealtimeSamples" Collapsed="true">
<Position X="6.25" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AEAAAAAABAAAEABAAAAABBAAAAAAAAAAAAAAgEIAEEA=</HashCode>
<FileName>RealtimeCommands\GetRealtimeSamples.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.GetRealtimeSamplesSLICE2" Collapsed="true">
<Position X="5" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAA=</HashCode>
<FileName>RealtimeCommands\GetRealtimeSamplesSLICE2.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.GetRealtimeSamplesSLICE6" Collapsed="true">
<Position X="7.25" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAA=</HashCode>
<FileName>RealtimeCommands\GetRealtimeSamplesSLICE6.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.RealtimeCommandBase" Collapsed="true">
<Position X="7.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>RealtimeCommands\RealtimeCommandBase.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.RealtimeStreamDecoder" Collapsed="true">
<Position X="0.5" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAABAACAAAAAAABAgAgAAAAAAQAAAAAAAAAAAAgAEAA=</HashCode>
<FileName>RealtimeCommands\RealtimeStreamDecoder.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.RealtimeStreamingNextSamples" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="2.25" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>EgABAACAAAAAAABAAAAABABAAAIBAAAAQAAAgAABEAA=</HashCode>
<FileName>RealtimeCommands\RealtimeStreamingNextSamples.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.RetrieveSampleAverage" Collapsed="true">
<Position X="2.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAABAQAAAAIAAAABBBAAAAAAAAgAAAAgEAAEEA=</HashCode>
<FileName>RealtimeCommands\RetrieveSampleAverage.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.RetrieveSingleSample" Collapsed="true">
<Position X="9.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAABAAAAAAAAAAABBAAAAAAAAAAAAAAAEAAEEA=</HashCode>
<FileName>RealtimeCommands\RetrieveSingleSample.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.StartRealtimeMode" Collapsed="true">
<Position X="11.75" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAACAAAAAAABAAAAAAAAAAABAAAAAAAAA=</HashCode>
<FileName>RealtimeCommands\StartRealtimeMode.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.DASLib.Command.SLICE.RealtimeCommands.StartRealtimeStreamingMode" Collapsed="true">
<Position X="14" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>AABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAQAAAAAA=</HashCode>
<FileName>RealtimeCommands\StartRealtimeStreamingMode.cs</FileName>
</TypeIdentifier>
</Class>
<Interface Name="DTS.DASLib.Command.SLICE.RealtimeCommands.IGetRealtimeSamples" Collapsed="true">
<Position X="0.5" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AgAAAAAAAAAAAABAAAAABAAAAAAAAAAAAAQAgAAAEAA=</HashCode>
<FileName>RealtimeCommands\IGetRealtimeSamples.cs</FileName>
</TypeIdentifier>
</Interface>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// this is ported from FirmwareTestUtility where it was written by Loc Pham. It is included for
/// 10573 implement SW side of single command/streaming download
/// </summary>
public class DownloadByteConverter
{
public enum DlByteIndex
{
Sync = 0,
Type = 1,
Command = 2,
Status = 3,
Group = 4,
Id = 5,
Datalength = 6,
SequenceNumber = 8,
HeaderCRC = 10,
DataCRC = 12,
DataADCStartOffset = 14,
DataADCEndOffset = 22,
DataStart = 30
}
public ushort SeqNumber { get; }
public ushort SeqNumberPrev { get; }
public ulong DlAdcStartOffset { get; }
public ulong DlAdcEndOffset { get; }
public ulong DlStreamSampleNumber { get; }
public ushort[] DlData { get; }
public uint[] DlChannels { get; }
public DownloadByteConverter(byte[] bytes)
{
SeqNumber = GetUShort(bytes, (int)DlByteIndex.SequenceNumber);
DlAdcStartOffset = GetUInt(bytes, (int)DlByteIndex.DataADCStartOffset);
DlAdcStartOffset = GetULong(bytes, (int)DlByteIndex.DataADCEndOffset);
DlData = new ushort[(bytes.Length - (int)DlByteIndex.DataStart) / 2];
if (SeqNumber == 0)
{
SeqNumberPrev = 0;
}
else
{
if (SeqNumberPrev != 0 &&
SeqNumberPrev != SeqNumber - 1)
{
System.Diagnostics.Debug.WriteLine("sequence out of order: ");
System.Diagnostics.Debug.WriteLine(SeqNumberPrev.ToString());
System.Diagnostics.Debug.WriteLine(SeqNumber.ToString());
}
}
SeqNumberPrev = SeqNumber;
for (var idx = 0; idx < DlData.Length; idx++)
{
DlData[idx] = GetDownloadUShort(bytes, (int)(DlByteIndex.DataStart + idx * 2));
}
}
private static ulong GetULong(byte[] bytes, int offset)
{
return (ulong)bytes[offset + 7] << 0 |
(ulong)bytes[offset + 6] << 8 |
(ulong)bytes[offset + 5] << 16 |
(ulong)bytes[offset + 4] << 24 |
(ulong)bytes[offset + 3] << 32 |
(ulong)bytes[offset + 2] << 40 |
(ulong)bytes[offset + 1] << 48 |
(ulong)bytes[offset + 0] << 56;
}
private static ushort GetUShort(byte[] bytes, int offset)
{
return (ushort)(bytes[offset + 1] |
bytes[offset + 0] << 8);
}
private static uint GetUInt(byte[] bytes, int offset)
{
return (uint)bytes[offset + 3] << 0 |
(uint)bytes[offset + 2] << 8 |
(uint)bytes[offset + 1] << 16 |
(uint)bytes[offset + 0] << 32;
}
/// <summary>
/// data apparently has a different byte order than parameters, so we have to
/// rearrange byte order for parameters but not data.
/// </summary>
/// <param name="bytes"></param>
/// <param name="offset"></param>
/// <returns></returns>
private static ushort GetDownloadUShort(byte[] bytes, int offset)
{
return (ushort)(bytes[offset + 0] | bytes[offset + 1] << 8);
}
}
}

View File

@@ -0,0 +1,42 @@
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public abstract class EventDataCommands : CommandBase
{
protected enum Commands
{
Reserved = 0x00,
ResetEventList = 0x01,
QueryTotalEventCount = 0x02,
QueryMatchingEvents = 0x03,
QueryEventData = 0x04,
SetEventData = 0x05,
StartDownloadStreamData = 0x06, // CMDEVD_STREAM_EVENT_DATA_START
GetNextDownloadStreamDataSamples = 0x07, // stream packet of data out to receiver.
QueryUartEventInfo = 0x09, // saved UART info
QueryUartEventData = 0x0A,
SetUartEventData = 0x0B,
GenerateEvent = 0x0C,
QueryEthernetEventInfo = 0x0D,
QueryEthernetEventData = 0x0E,
SetEthernetEventData = 0x0F
};
protected abstract Commands Command { get; }
protected EventDataCommands(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.EventData;
command.SetCommand((byte)Command, Command.ToString());
}
protected EventDataCommands(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Type = CommandPacket.CommandType.EventData;
command.SetCommand((byte)Command, Command.ToString());
}
}
}

View File

@@ -0,0 +1,188 @@
using System;
using System.Text;
using DTS.Common.Enums.Communication;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
using DTS.Common.Utilities;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// This was ported from FirmwareTestUtility where it was written by Loc Pham
/// it is being included for
/// 10573 implement SW side of single command/streaming download
/// this command can be used to collect data that has been collecting in a buffer
/// from download streaming
/// </summary>
public class GetNextDownloadStreamDataSamples : EventDataCommands
{
protected override Commands Command => Commands.GetNextDownloadStreamDataSamples;
public GetNextDownloadStreamDataSamples(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
baseCommand = new CommandPacket();
LogCommands = false;
baseCommand.SetCommand((byte)Commands.GetNextDownloadStreamDataSamples, "GetNextDownloadStreamDataSamples");
}
public GetNextDownloadStreamDataSamples(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout)
: base(sock, msTimeout)
{
baseCommand = new CommandPacket();
LogCommands = false;
baseCommand.SetCommand((byte)Commands.GetNextDownloadStreamDataSamples, "GetNextDownloadStreamDataSamples");
}
public DownloadByteConverter DlData { get; private set; }
private ushort _lastSequenceProcessed = ushort.MaxValue;
private const int MAX_SEQUENCE_DIFF = 1000;
public void ProcessData()
{
var bytes = baseResponse.ToBytes();
var headerCrc = response.HeaderCRC;
response.ComputeCRCs();
if (headerCrc != response.HeaderCRC)
{
DlData = null;
return;
}
DlData = new DownloadByteConverter(bytes);
if (null == DlData) { return; }
if (_lastSequenceProcessed == DlData.SeqNumber)
{
DlData = null;
return;
}
var delta = Math.Abs(DlData.SeqNumber - _lastSequenceProcessed);
if (delta > MAX_SEQUENCE_DIFF && ushort.MaxValue != _lastSequenceProcessed && 0 != DlData.SeqNumber)
{
//per loc we shouldn't get here, the old code in the FWTU would apparently unintentionally throw an exception
//I've preserved that code in comments below
throw new Exception("sequence number overflow");
//DlData = null;
//_lastSequenceProcessed = DlData.SeqNumber;
//return;
}
_lastSequenceProcessed = DlData.SeqNumber;
}
/// <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
{
DlData = null;
// 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);
}
else if (baseResponse.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
// didn't go well
var msg = MakeLogString("SyncExecute: response.Status = " + baseResponse.Status);
LogCommand(false);
switch (baseResponse.Status)
{
case DFConstantsAndEnums.CommandStatus.StatusInvalidModeForCommand:
throw new CommandException(CommandErrorReason.InvalidMode, msg);
case DFConstantsAndEnums.CommandStatus.StatusUnimplemented:
case DFConstantsAndEnums.CommandStatus.StatusInvalidCommand:
case 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);
LogCommand(false);
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
}
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveTimeout:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
}
case CommunicationConstantsAndEnums.CommunicationResult.SendFailed:
case CommunicationConstantsAndEnums.CommunicationResult.SendTimeout:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.SendFailed, msg);
}
default:
{
var msg = MakeLogString("SyncExecute: Unknown ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new Exception(msg);
}
}
}
finally
{
recorder.ExecuteIsBusy = false;
}
}
}
}

View File

@@ -0,0 +1,117 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// retrieves Ethernet data from an EthernetRecorder
/// </summary>
public class QueryEthernetEventData : EventDataCommands
{
private ushort _eventID = 0;
public ushort EventID
{
get => _eventID;
set { _eventID = value; command.SetParameter(0, _eventID); }
}
protected override Commands Command => Commands.QueryEthernetEventData;
private uint _requestByteCount = 0;
public uint RequestByteCount
{
get => _requestByteCount;
set { _requestByteCount = value; command.SetParameter(2, _requestByteCount); }
}
private ulong _StartDataOffsetBytes = 0UL;
public ulong StartDataOffsetBytes
{
get => _StartDataOffsetBytes;
set { _StartDataOffsetBytes = value; command.SetParameter(6, _StartDataOffsetBytes); }
}
private byte[] _data;
public byte[] Data
{
get => _data;
set
{
if (null == value) { return; }
_data = value;
}
}
private const int PARAMETER_BYTE_COUNT = 14;
public QueryEthernetEventData(ICommunication sock)
: base(sock)
{
command.Parameter = new byte[PARAMETER_BYTE_COUNT];
/*
Byte [1:0] U16 Event ID
Byte [5:2] U32 Request byte count.
Byte [13:6] U64 Start data offset in byte counter.
*/
}
public QueryEthernetEventData(ICommunication sock, int timeoutMS)
: base(sock, timeoutMS)
{
command.Parameter = new byte[PARAMETER_BYTE_COUNT];
/*
Byte [1:0] U16 Event ID
Byte [5:2] U32 Request byte count.
Byte [13:6] U64 Start data offset in byte counter.
*/
}
protected override CommandReceiveAction WholePackage()
{
/*
Byte [1:0]: U16 Event ID
Byte [5:2]: U32 Payload length in byte count.
Byte [13:6]: U64 data offset start.
Byte [payloadLength]: Data byte stream with payload length firmware can fit to a response payload size or that of request whichever less.
*/
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
if (response.ParameterLength > 0)
{
response.GetParameter(0, out _eventID);
response.GetParameter(2, out uint payloadLength);
response.GetParameter(6, out _StartDataOffsetBytes);
_data = new byte[payloadLength];
for (var i = 0; i < payloadLength; i++)
{
response.GetParameter(PARAMETER_BYTE_COUNT + i, out _data[i]);
}
}
else { _eventID = 0; }
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>()
{
$"Event ID: {EventID}",
$"StartDataOffset: {StartDataOffsetBytes}",
$"RequestByteCount: {RequestByteCount}"
});
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"Event ID: {EventID}",
$"Payload(bytes): {_data.Length}",
$"StartDataOffsetBytes: {StartDataOffsetBytes}"
});
}
}
}

View File

@@ -0,0 +1,96 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// Retrieves parameters of Ethernet data recorder by EthernetRecorder
/// </summary>
public class QueryEthernetEventInfo : EventDataCommands
{
protected override Commands Command => Commands.QueryEthernetEventInfo;
private ushort _eventID = 0;
public ushort EventID
{
get { return _eventID; }
set { _eventID = value; command.SetParameter(0, _eventID); }
}
private ushort _dataDownloaded = 0;
public ushort DataDownloaded => _dataDownloaded;
private ulong _totalByteCount = 0UL;
public ulong TotalByteCount => _totalByteCount;
private ulong _triggerByteCount = 0UL;
public ulong TriggerByteCount => _triggerByteCount;
private ulong _faultByteCount;
public ulong FaultByteCount => _faultByteCount;
private uint[] _DataStartTimeStamp = new uint[] { 0, 0 };
public uint[] DataStartTimeStamp => _DataStartTimeStamp;
public QueryEthernetEventInfo(ICommunication sock)
: base(sock)
{
//Command Parameters: 4 bytes.
//Byte[1:0] U16 Event ID.
//Byte[3:2]: Reserved.
command.Parameter = new byte[4];
}
public QueryEthernetEventInfo(ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
//Command Parameters: 4 bytes.
//Byte[1:0] U16 Event ID.
//Byte[3:2]: Reserved.
command.Parameter = new byte[4];
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
if (response.ParameterLength > 0)
{
/*
Response: 36 bytes.
Byte [1:0] U16 Event ID.
Byte [3:2] U16 Data Downloaded Flag.
Byte [11:4] U64 Total ByteCount.
Byte [19:12] U64 Trigger ByteCount.
Byte [27:20] U64 Fault ByteCount.
Byte [35:28] U32[2] Data Start Timestamp. U32[0] = Second. U32[1] = Nano-Second
*/
response.GetParameter(0, out _eventID);
response.GetParameter(2, out _dataDownloaded);
response.GetParameter(4, out _totalByteCount);
response.GetParameter(12, out _triggerByteCount);
response.GetParameter(20, out _faultByteCount);
response.GetParameter(28, out uint temp);
_DataStartTimeStamp[0] = temp;
response.GetParameter(32, out temp);
_DataStartTimeStamp[1] = temp;
}
else { _eventID = 0; }
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"EventId: {EventID}",
$"DataDownloaded: {DataDownloaded}",
$"TotalByteCount: {TotalByteCount}",
$"TriggerByteCount: {TriggerByteCount}",
$"FaultByteCount: {FaultByteCount}",
$"DataStartTimeStamp: {DataStartTimeStamp[0]}, {DataStartTimeStamp[1]}"
});
}
}
}

View File

@@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using DTS.Common.DASResource;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class QueryEventDataBase : EventDataCommands
{
protected override Commands Command => Commands.QueryEventData;
private const ushort ADC_OFFSET = 0x8000;
public const byte ALL_CHANNELS = 0xFF;
protected UInt16 _eventNumber;
protected UInt64 _firstSample;
protected UInt64 _lastSample;
protected UInt64 _samplesDownloaded;
protected byte _channel;
protected int _channelsDownloaded;
protected ushort[] _data;
public UInt16 EventNumber
{
get => _eventNumber;
set { _eventNumber = value; command.SetParameter(0, _eventNumber); }
}
public virtual UInt64 FirstSample
{
get => _firstSample;
set { _firstSample = value; command.SetParameter(2, _firstSample); }
}
public virtual UInt64 LastSample
{
get => _lastSample;
set { _lastSample = value; command.SetParameter(10, _lastSample); }
}
public byte Channel
{
get => _channel;
set
{
_channel = value; command.SetParameter(18, _channel);
ChannelsDownloaded = 0xFF == _channel ? 3 : 1;
}
}
public int ChannelsDownloaded
{
get => _channelsDownloaded;
set => _channelsDownloaded = value;
}
public int Count => (int)_samplesDownloaded;
public QueryEventDataBase(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[19];
_data = null;
_eventNumber = 0;
_firstSample = 0;
_lastSample = 0;
_channel = 0;
command.ShouldLog = false;
}
public QueryEventDataBase(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Parameter = new byte[19];
_data = null;
_eventNumber = 0;
_firstSample = 0;
_lastSample = 0;
_channel = 0;
command.ShouldLog = false;
}
public override void Execute(CommandCallback cb, object cbData)
{
// Do a little parameter checking
if (_firstSample > _lastSample)
{
// "QueryEventData.Execute: First Sample cannot be greater than Last Sample"
throw new ApplicationException(Strings.QueryEventData_Execute_Err1);
}
base.Execute(cb, cbData);
}
protected override CommandReceiveAction WholePackagePost()
{
// now send the data to the user
var stat = CommandStatus.Success;
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
var s = (int)response.Status;
APILogger.LogString("QueryEventData.WholePackagePost: reporting failure, status==" + CommandPacketBase.StatusLabels[s] + " (0x" + s.ToString("X") + ")");
stat = CommandStatus.Failure;
}
var cbReport = new QueryEventDataReport(stat, UserCallbackData);
cbReport.Data = new short[_channelsDownloaded][];
for (var i = 0; i < _channelsDownloaded; i++)
GetChannelData(i, out cbReport.Data[i]);
return UserCallback(cbReport);
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
return CommandReceiveAction.StopReceiving;
}
_samplesDownloaded = (ulong)(response.Parameter.Length / 2) / (ulong)_channelsDownloaded;
_data = new ushort[_samplesDownloaded * (ulong)_channelsDownloaded];
for (var i = 0; (ulong)i < _samplesDownloaded * (ulong)_channelsDownloaded; i++)
{
response.GetParameter(2 * i, out _data[i]);
}
return CommandReceiveAction.StopReceiving;
}
public override void SyncExecute()
{
// Do a little parameter checking
if (_firstSample > _lastSample)
{
// "QueryEventData.SyncExecute: First Sample cannot be greater than Last Sample"
throw new ApplicationException(Strings.QueryEventData_SyncExecute_Err1);
}
base.SyncExecute();
}
public virtual void GetChannelData(int channel, out short[] signedADC)
{
if (channel < 0 || channel > _channelsDownloaded)
{
// "QueryEventData.GetChannelData: Data requested on a channel that wasn't downloaded."
throw new ApplicationException(Strings.QueryEventData_GetChannelData_Err1);
}
// Data order for a 9 channel stack
// 7 8 9 4 5 6 1 2 3 7 8 9 4 5 6 1 2 3 etc.
var rv = new short[_samplesDownloaded];
var sliceNumber = channel / 3;
var sliceOffset = (_channelsDownloaded / 3 - sliceNumber - 1) * 3;
if (sliceOffset < 0) sliceOffset = 0;
var channelInSlice = channel % 3;
for (var i = 0; i < rv.Length; i++)
{
rv[i] = (short)(_data[i * _channelsDownloaded + sliceOffset + channelInSlice] - ADC_OFFSET);
}
signedADC = rv;
}
public virtual void GetRawIndexedData(int index, out ushort[] data)
{
data = new ushort[_samplesDownloaded];
for (var i = 0; i < data.Length; i++)
{
data[i] = _data[i * _channelsDownloaded + index];
}
}
public override void CommandToString(ref List<List<string>> lines)
{
lines.Add(new List<string> { $"Event number: {EventNumber}, First sample: {FirstSample}, Last sample: {LastSample}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
lines.Add(new List<string>
{
$"ChannelsDownloaded: {ChannelsDownloaded}, Count: {Count}"
});
}
public void LogResponse()
{
LogCommand(false);
}
}
}

View File

@@ -0,0 +1,15 @@
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class QueryEventDataReport : ICommandReport
{
public object CallbackObject { get; set; }
public CommandStatus Status { get; set; }
public short[][] Data { get; set; }
public QueryEventDataReport(CommandStatus status, object cbData)
{
Status = status;
CallbackObject = cbData;
}
}
}

View File

@@ -0,0 +1,45 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class QueryTotalEventCount : EventDataCommands
{
protected override Commands Command => Commands.QueryTotalEventCount;
private ushort _count;
public ushort Count => _count;
public QueryTotalEventCount(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryTotalEventCount(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
if (response.ParameterLength > 0)
{
response.GetParameter(0, out _count);
}
else { _count = 0; }
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>
{
$"Count: {Count}"
});
}
}
}

View File

@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class QueryUARTEventData : EventDataCommands
{
public const int MAX_DATA_LENGTH = 2000;
public const int PAYLOAD_HEADER_LENGTH = 14;
protected override Commands Command => Commands.QueryUartEventData;
protected ushort _eventNumber;
protected uint _requestByteCount;
protected ulong _requestOffsetByteCount;
protected uint _payloadByteCount;
protected ulong _payloadOffsetByteCount;
protected byte[] _data;
public ushort EventNumber
{
get => _eventNumber;
set { _eventNumber = value; command.SetParameter(0, _eventNumber); }
}
public uint RequestByteCount
{
get => _requestByteCount;
set { _requestByteCount = value; command.SetParameter(2, _requestByteCount); }
}
public ulong RequestOffsetByteCount
{
get => _requestOffsetByteCount;
set { _requestOffsetByteCount = value; command.SetParameter(6, _requestOffsetByteCount); }
}
public uint PayloadByteCount => _payloadByteCount;
public ulong PayloadOffsetByteCount => _payloadOffsetByteCount;
public byte[] PayloadData => _data;
public QueryUARTEventData(ICommunication sock) : base(sock)
{
command.Parameter = new byte[14];
_data = null;
_eventNumber = 0;
_requestByteCount = 0;
_requestOffsetByteCount = 0;
_payloadByteCount = 0;
_payloadOffsetByteCount = 0;
command.ShouldLog = false;
}
public QueryUARTEventData(ICommunication sock, int timeoutMillisec) : base(sock, timeoutMillisec)
{
command.Parameter = new byte[14];
_data = null;
_eventNumber = 0;
_requestByteCount = 0;
_requestOffsetByteCount = 0;
_payloadByteCount = 0;
_payloadOffsetByteCount = 0;
command.ShouldLog = false;
}
public override void Execute(CommandCallback cb, object cbData)
{
// Do a little parameter checking
_data = null;
base.Execute(cb, cbData);
}
protected override CommandReceiveAction WholePackagePost()
{
// now send the data to the user
var stat = CommandStatus.Success;
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
var s = (int)response.Status;
APILogger.LogString("QueryUARTEventData.WholePackagePost: reporting failure, status==" + CommandPacketBase.StatusLabels[s] + " (0x" + s.ToString("X") + ")");
stat = CommandStatus.Failure;
}
var cbReport = new QueryEventDataReport(stat, UserCallbackData);
//cbReport.Data = new short[_channelsDownloaded][];
//for (var i = 0; i < _channelsDownloaded; i++)
// GetChannelData(i, out cbReport.Data[i]);
return UserCallback(cbReport);
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
return CommandReceiveAction.StopReceiving;
}
response.GetParameter(0, out ushort responseEventNum);
response.GetParameter(2, out _payloadByteCount);
response.GetParameter(6, out _payloadOffsetByteCount);
_data = new byte[_payloadByteCount];
for (var i = 0; i < _payloadByteCount; i++)
{
response.GetParameter(PAYLOAD_HEADER_LENGTH + i, out _data[i]);
}
return CommandReceiveAction.StopReceiving;
}
public override void SyncExecute()
{
// Do a little parameter checking
_data = null;
base.SyncExecute();
}
public override void CommandToString(ref List<List<string>> lines)
{
lines.Add(new List<string> { $"Event number: {EventNumber}, RequestByteCount: {RequestByteCount}, OffsetByteCount: {RequestOffsetByteCount}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
lines.Add(new List<string>
{
$"PayloadByteCount: {PayloadByteCount}, OffsetByteCount: {PayloadOffsetByteCount}"
});
}
public void LogResponse()
{
LogCommand(false);
}
}
}

View File

@@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Strings;
using DTS.Common.Utilities.Logging;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class QueryUARTEventInfo : EventDataCommands
{
protected override Commands Command => Commands.QueryUartEventInfo;
protected ushort _eventNumber;
protected ushort _dataPresent;
protected ushort _dataDownloaded;
protected ulong _totalByteCount;
protected ulong _triggerByteCount;
protected ulong _faultByteCount;
protected uint _startTimestamp;
protected uint _endTimestamp;
protected uint _baudrate;
public ushort EventNumber
{
get => _eventNumber;
set { _eventNumber = value; command.SetParameter(0, _eventNumber); }
}
public QueryUARTEventInfo(ICommunication sock) : base(sock)
{
command.Parameter = new byte[2];
_eventNumber = 0;
_dataPresent = 0;
_dataDownloaded = 0;
_totalByteCount = 0;
_triggerByteCount = 0;
_faultByteCount = 0;
_startTimestamp = 0;
_endTimestamp = 0;
_baudrate = 0;
command.ShouldLog = false;
}
public QueryUARTEventInfo(ICommunication sock, int timeoutMillisec) : base(sock, timeoutMillisec)
{
command.Parameter = new byte[2];
_eventNumber = 0;
_dataPresent = 0;
_dataDownloaded = 0;
_totalByteCount = 0;
_faultByteCount = 0;
_triggerByteCount = 0;
_startTimestamp = 0;
_endTimestamp = 0;
_baudrate = 0;
command.ShouldLog = false;
}
public bool DataPresent => 1 == _dataPresent;
public bool DataDownloaded => 1 == _dataDownloaded;
public ulong TotalByteCount => _totalByteCount;
public ulong TriggerByteCount => _triggerByteCount;
public ulong FaultByteCount => _faultByteCount;
public uint StartTimestamp => _startTimestamp;
public uint EndTimestamp => _endTimestamp;
public uint BaudRate => _baudrate;
public override void Execute(CommandCallback cb, object cbData)
{
// Do a little parameter checking
base.Execute(cb, cbData);
}
protected override CommandReceiveAction WholePackagePost()
{
// now send the data to the user
var stat = CommandStatus.Success;
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
var s = (int)response.Status;
APILogger.LogString("QueryUARTEventInfo.WholePackagePost: reporting failure, status==" + CommandPacketBase.StatusLabels[s] + " (0x" + s.ToString("X") + ")");
stat = CommandStatus.Failure;
}
var cbReport = new QueryEventDataReport(stat, UserCallbackData);
//cbReport.Data = new short[_channelsDownloaded][];
//for (var i = 0; i < _channelsDownloaded; i++)
// GetChannelData(i, out cbReport.Data[i]);
return UserCallback(cbReport);
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
return CommandReceiveAction.StopReceiving;
}
response.GetParameter(0, out ushort responseEventNum);
response.GetParameter(2, out _dataPresent);
response.GetParameter(4, out _dataDownloaded);
response.GetParameter(8, out _totalByteCount);
response.GetParameter(16, out _triggerByteCount);
response.GetParameter(24, out _faultByteCount);
response.GetParameter(32, out _startTimestamp);
response.GetParameter(36, out _endTimestamp);
response.GetParameter(40, out _baudrate);
return CommandReceiveAction.StopReceiving;
}
public override void SyncExecute()
{
// Do a little parameter checking
base.SyncExecute();
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"Event number: {EventNumber}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>
{
$"DataPresent: {DataPresent}, DataDownloaded: {DataDownloaded}, TotalByteCount: {TotalByteCount}, TriggerByteCount: {TriggerByteCount}, StartTimestamp: {StartTimestamp}, EndTimestamp: {EndTimestamp}"
});
}
public void LogResponse()
{
LogCommand(false);
}
}
}

View File

@@ -0,0 +1,19 @@
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
public class ResetEventList : EventDataCommands
{
protected override Commands Command => Commands.ResetEventList;
public ResetEventList(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public ResetEventList(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
}
}

View File

@@ -0,0 +1,64 @@
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// this was ported almost directly from FirmwareTestUtility, where it was written by Loc Pham
/// this was done for
/// 10573 implement SW side of single command/streaming download
/// this command should put SLICE2 firmware >= A1N4 into download streaming mode
/// any command should be sufficient to stop this streaming early
/// </summary>
public class StartDownloadStreamData : EventDataCommands
{
protected override Commands Command => Commands.StartDownloadStreamData;
public StartDownloadStreamData(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[18];
}
public StartDownloadStreamData(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Parameter = new byte[18];
}
public const byte AllChannels = 0xFF;
private ushort _eventNumber;
private ulong _firstSample;
private ulong _lastSample;
public ushort EventNumber
{
get => _eventNumber;
set
{
_eventNumber = value;
command.SetParameter(0, _eventNumber);
}
}
public virtual ulong FirstSample
{
get => _firstSample;
set
{
_firstSample = value;
command.SetParameter(2, _firstSample);
}
}
public virtual ulong LastSample
{
get => _lastSample;
set
{
_lastSample = value;
command.SetParameter(10, _lastSample);
}
}
}
}

View File

@@ -0,0 +1,559 @@
using System;
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE
{
public abstract class FirmwareUpdateCommands : CommandBase
{
protected enum Commands
{
Reserved = 0x00,
QueryFirmwareUpdateBlockSize = 0x01,
QueryBootloaderVersion = 0x02,
SwitchToFirmwareUpdateMode = 0x03,
BeginFirmwareUpdate = 0x04,
ProgramFirmwareUpdateBlock = 0x05,
FinishFirmwareUpdate = 0x06,
Reboot = 0x07,
QueryInFirmwareUpdateMode = 0x08,
// added to support slice pro (Bridge/IEPE) firmware update via USB.
Load_SliceProStackFirmwareImage = 0x09, // CMDFW_LOAD_STACK_FW, // = 0x09, loading (in 400-byte blocks) firmware image to base NAND.
Query_SliceProStackFirmwareImage = 0x0A, // CMDFW_QUERY_STACK_FW, // = 0x0A, reading block (in 400-byte blocks) of firmware image from base NAND at a time.
Query_SliceProStackFirmwareCRC = 0x0B, // CMDFW_QUERY_STACK_FW_CRC, // = 0x0B, read firmware CRC for validation purpose.
Start_SliceProStackFirmwareUpdate = 0x0C, // CMDFW_START_STACK_FW_UPDADE, // = 0x0C, stack module to be upgraded with firmware.
Stop_SliceProStackFirmwareUpdate = 0x0D, // CMDFW_STOP_STACK_FW_UPDADE, // = 0x0D, stop firmware upgrade for after completes the on-going one.
Query_SliceProStackFirmwareUpdateMode = 0x0E, // CMDFW_QUERY_STACK_FW_UPDATE_MODE, // = 0x0E, polling updatae mode from stack
Set_SliceProStackFirmwareUpdateMode = 0x0F, // CMDFW_SET_STACK_FW_UPDATE_MODE, // = 0x0F, Set stack module to update mode
MAX_CMDFW_COMMAND // = 0x10
};
public enum FirmwareMode
{
FW = 0,
BL = 1,
BLL = 2,
};
//protected const int MIN_SLICE2_FILEDATA_PROTOCOL = 130; //SLICE 2 Protocol cmd
protected const int MAX_FILE_ID = 30; // user = 10, firmware = 20, max internally = 65. 10;
protected const int MAX_FILE_LENGTH = 400;
protected abstract Commands _Command { get; }
protected FirmwareUpdateCommands(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
protected FirmwareUpdateCommands(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
}
public class QueryFirmwareUpdateBlockSize : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.QueryFirmwareUpdateBlockSize;
private ushort _size;
public ushort BlockSize => _size;
public QueryFirmwareUpdateBlockSize(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
_size = 0;
}
public QueryFirmwareUpdateBlockSize(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
_size = 0;
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _size);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>()
{
$"BlockSize: {BlockSize}"
});
}
}
public class QueryBootloaderVersion : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.QueryBootloaderVersion;
private string _version = string.Empty;
public string Version => _version;
public QueryBootloaderVersion(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryBootloaderVersion(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _version);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"Version: {Version}"
});
}
}
public class SwitchToFirmwareUpdateMode : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.SwitchToFirmwareUpdateMode;
public SwitchToFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public SwitchToFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class BeginFirmwareUpdate : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.BeginFirmwareUpdate;
public BeginFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public BeginFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class ProgramFirmwareUpdateBlock : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.ProgramFirmwareUpdateBlock;
private uint _address;
private ushort _blockcrc;
private ushort _upperlower;
private byte[] _data;
public uint BlockBaseAddress
{
get => _address;
set
{
_address = value;
command.SetParameter(0, _address);
}
}
public ushort BlockSize { get; private set; }
public ushort BlockCRC16
{
get => _blockcrc;
set
{
_blockcrc = value;
command.SetParameter(6, _blockcrc);
}
}
public bool Upper
{
get => _upperlower == 1 ? true : false;
set
{
if (value)
{
_upperlower = 1;
command.SetParameter(8, _upperlower);
}
}
}
public byte[] Data
{
get => _data;
set
{
if (null == value)
{
return;
}
_data = value;
if (command.Parameter.Length < value.Length + 10)
{
var newparameter = new byte[value.Length + 10];
BlockSize = (ushort)value.Length;
command.SetParameter(4, BlockSize);
Buffer.BlockCopy(command.Parameter, 0,
newparameter, 0, 10);
command.Parameter = newparameter;
Buffer.BlockCopy(_data, 0, command.Parameter, 10, _data.Length);
}
}
}
public ProgramFirmwareUpdateBlock(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[10];
Upper = false;
}
public ProgramFirmwareUpdateBlock(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[10];
Upper = false;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>() { $"BlockBaseAddress: {BlockBaseAddress}, BlockSize: {BlockSize}, BlockCRC16: {BlockCRC16}, Upper: {Upper}" });
}
}
public class FinishFirmwareUpdate : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.FinishFirmwareUpdate;
private ushort _imagecrc;
public ushort ImageCRC16
{
get => _imagecrc;
set
{
_imagecrc = value;
command.SetParameter(0, _imagecrc);
}
}
public FinishFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[2];
}
public FinishFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[2];
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>() { $"ImageCRC16: {ImageCRC16}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"ImageCRC16: {ImageCRC16}"
});
}
}
public class Reboot : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.Reboot;
public Reboot(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public Reboot(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
}
public class QueryInFirmwareUpdateMode : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.QueryInFirmwareUpdateMode;
private byte _updateMode = (byte)FirmwareMode.FW;
public bool InUpdateMode => FirmwareMode.FW != (FirmwareMode)_updateMode;
public bool IsFwMode => FirmwareMode.FW == (FirmwareMode)_updateMode;
public bool IsBlMode => FirmwareMode.BL == (FirmwareMode)_updateMode;
public bool IsBllMode => FirmwareMode.BLL == (FirmwareMode)_updateMode;
public FirmwareMode Mode => (FirmwareMode)_updateMode;
public QueryInFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryInFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _updateMode);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
string.Format($"UpdateMode: {(FirmwareMode)_updateMode}")
});
}
}
/// <summary>
///These stack firmware command updates need at least protocol version 137
///No parameter. All slice in bootloader mode will be updated with new firmware.
/// </summary>
///
public class Load_SliceProStackFirmwareImage : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.Load_SliceProStackFirmwareImage;
#region Private Variables
private readonly ushort _fileID; //Byte 0-1: 16-bit file ID ranges from 1-10.
private uint _startByteCount;
private byte[] _data;
private static byte PARAM_NUM = 6;
#endregion
#region Command Parameters
public uint StartByteCount
{
get => _startByteCount;
set { _startByteCount = value; command.SetParameter(2, _startByteCount); }
}
public byte[] Data
{
get => _data;
set
{
if (null == value)
{
return;
}
if (MAX_FILE_LENGTH < value.Length)
{
throw new NotImplementedException();
}
_data = value;
//if (this.command.Parameter.Length < value.Length+ PARAM_NUM)
//{
byte[] newparameter = new byte[value.Length + PARAM_NUM];
Buffer.BlockCopy(command.Parameter, 0, newparameter, 0, PARAM_NUM);
Size = value.Length;
command.Parameter = newparameter;
Buffer.BlockCopy(_data, 0, command.Parameter, PARAM_NUM, _data.Length);
//}
}
}
public int Size { get; private set; }
public int MaximumFileStreamBytes => MAX_FILE_LENGTH;
#endregion
#region Command Functions
public Load_SliceProStackFirmwareImage(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[PARAM_NUM];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
_data = null;
_fileID = 20;
command.SetParameter(0, _fileID);
_startByteCount = 0;
command.ShouldLog = false;
}
public Load_SliceProStackFirmwareImage(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[PARAM_NUM];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
_data = null;
_fileID = 20;
command.SetParameter(0, _fileID);
_startByteCount = 0;
command.ShouldLog = false;
}
#endregion
#region Log Functions
public override void CommandToString(ref List<List<string>> lines)
{
lines.Add(new List<string>() { $"Store ID: {_fileID}, Start Byte: {StartByteCount}, End Byte: {Size + StartByteCount}" });
}
public void LogResponse()
{
LogCommand(false);
}
#endregion
}
public class Start_SliceProStackFirmwareUpdate : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.Start_SliceProStackFirmwareUpdate;
public Start_SliceProStackFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
public Start_SliceProStackFirmwareUpdate(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
}
public class Set_SliceProStackFirmwareUpdateMode : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.Set_SliceProStackFirmwareUpdateMode;
private int _sliceCount = 0;
private byte[] _sliceProUpdateMode;
public int SliceModuleCount
{
get => _sliceCount;
set
{
_sliceCount = value;
_sliceProUpdateMode = new byte[_sliceCount];
}
}
public byte[] SliceModuledateMode
{
get => _sliceProUpdateMode;
set
{
for (int i = 0; i < _sliceCount; i++)
{
_sliceProUpdateMode[i] = value[i];
}
command.Parameter = _sliceProUpdateMode;
}
}
public Set_SliceProStackFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
public Set_SliceProStackFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
}
public class Get_SliceProStackFirmwareUpdateMode : FirmwareUpdateCommands
{
protected override Commands _Command => Commands.Query_SliceProStackFirmwareUpdateMode;
public int SliceModuleCount { get; private set; } = 0;
public byte[] SliceModuledateMode { get; private set; }
public Get_SliceProStackFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
public Get_SliceProStackFirmwareUpdateMode(DTS.Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate);
command.Type = CommandPacket.CommandType.FirmwareUpdate;
command.SetCommand((byte)_Command, _Command.ToString());
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
SliceModuleCount = response.Parameter.Length;
SliceModuledateMode = new byte[SliceModuleCount];
for (int i = 0; i < SliceModuleCount; i++)
{
response.GetParameter(i, out SliceModuledateMode[i]);
}
}
return CommandReceiveAction.StopReceiving;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
// ReSharper disable once InconsistentNaming
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MACTableEntry
{
public ushort Age { get; }
public ushort Port { get; }
public ushort Filter { get; }
// ReSharper disable once InconsistentNaming
public byte[] MAC { get; }
public MACTableEntry(ushort age, ushort port, ushort filter, byte[] mac)
{
Age = age;
Port = port;
Filter = filter;
MAC = mac;
}
}
public class DiscoveredConnectedSlice
{
public string DeviceMAC { get; }
public MACTableEntry[] ConnectedDevices { get; }
public DiscoveredConnectedSlice(string deviceMAC, MACTableEntry[] devices)
{
DeviceMAC = deviceMAC;
ConnectedDevices = devices;
}
}
}

View File

@@ -0,0 +1,226 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using DTS.DASLib.Command.Classes;
using DTS.Common.Utilities.Logging;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastAutoDiscover : MulticastCommandBase
{
#region constants and enums
private const int COMMAND_PAYLOAD_SIZE = 63;
private const int RESPONSE_PAYLOAD_SIZE = 278;
#endregion
#region private/protected properties
protected override Commands Command => Commands.AutoDiscover;
protected override bool StopAfterFirstMessage => false;
private uint _deviceClass;
private byte _responseOption;
private IPAddress _address;
private int _port = (int)Ports.Response;
private byte _dhcpEnabled;
private string _ip;
private string _subnet;
private string _gateway;
private string _dns;
private byte _isConnected;
private string _connectedIp;
private ushort _id;
private string _serialNumber;
private string _location;
private string _version;
private string _buildId;
#endregion
#region public properties
public List<IDiscoveredDevice> DiscoveredDevices { get; } = new List<IDiscoveredDevice>();
public TextLogger Logger { get; set; }
public DFConstantsAndEnums.MultiCastDeviceClasses DeviceClass { set { _deviceClass = (uint)value; command.SetParameter(36, (int)_deviceClass); } }
public ResponseOptions ResponseOption { set { _responseOption = (byte)value; command.SetParameter(40, _responseOption); } }
public IPAddress Address { set { _address = value; SetMulticastConfig(); } }
#endregion
#region methods
private void SetMulticastConfig()
{
IPAddress.TryParse(MulticastReceiveAddress, out _address);
var config = $"{_address}:{ResponsePort}";
command.SetParameter(41, config);
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
response.GetParameter(HOST_MAC_ADDRESS_OFFSET, out ResponseHostMac);
//we want to accept the response - even if it was sent on a
//a different mac address ...
if (response.ParameterLength < RESPONSE_PAYLOAD_SIZE)
{
response.Status = DFConstantsAndEnums.CommandStatus.StatusAttributeInvalidLength;
return CommandReceiveAction.StopReceiving;
}
response.GetParameter(CLIENT_MAC_ADDRESS_OFFSET, out ResponseClientMac);
response.GetParameter(36, out _deviceClass);
response.GetParameter(40, out _dhcpEnabled);
response.GetParameter(41, out _ip);
response.GetParameter(57, out _subnet);
response.GetParameter(73, out _gateway);
response.GetParameter(89, out _dns);
response.GetParameter(105, out _id);
response.GetParameter(107, out _isConnected);
response.GetParameter(108, out _serialNumber);
response.GetParameter(118, out _location);
response.GetParameter(198, out _version);
response.GetParameter(230, out _buildId);
response.GetParameter(262, out _connectedIp);
var sb = new StringBuilder();
//String.Format("{0,-27}", s);
sb.AppendFormat("SerialNumber {0}\r\n", _serialNumber);
sb.AppendFormat("ResponseClientMac {0}\r\n", ResponseClientMac);
sb.AppendFormat("IP {0}\r\n", _ip);
sb.AppendFormat("Location {0}\r\n", _location);
sb.AppendFormat("Id {0}\r\n", _id);
sb.AppendFormat("Version {0}\r\n", _version);
sb.AppendFormat("BuildId {0}\r\n", _buildId);
Log(sb.ToString());
var slice = new DiscoveredDevice
{
Mac = ResponseClientMac.Replace('-', ':'),
DevClass = (DFConstantsAndEnums.MultiCastDeviceClasses)_deviceClass,
Dhcp = Convert.ToBoolean(_dhcpEnabled),
Ip = _ip,
Subnet = _subnet,
Gateway = _gateway,
Dns = _dns,
SystemId = _id,
Connected = Convert.ToBoolean(_isConnected)
};
try
{
if (slice.DevClass == DFConstantsAndEnums.MultiCastDeviceClasses.S6DB ||
slice.DevClass == DFConstantsAndEnums.MultiCastDeviceClasses.Slice6)
{
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
slice.ConnectedIp = _connectedIp;
if (string.Empty != _connectedIp)
{
try
{
IPAddress connectedAddress;
IPAddress.TryParse(_connectedIp, out connectedAddress);
var hostName = Dns.GetHostEntry(connectedAddress);
slice.ConnectedHost = hostName.HostName;
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
slice.Serial = _serialNumber;
slice.Location = _location;
slice.FirmwareVersion = _version;
slice.BuildId = _buildId;
DiscoveredDevices.Add(slice);
return CommandReceiveAction.StopReceiving;
}
// ReSharper disable once InconsistentNaming
private static ConnectedEthernetDevice[] ParseSSIData(string data, DFConstantsAndEnums.MultiCastDeviceClasses type)
{
var connections = new List<ConnectedEthernetDevice>();
var lines = data.Replace("\r", "").Split('\n');
foreach (var line in lines)
{
var columns = line.Split(',');
if (columns.Length < 4) { continue; }
if (!char.IsNumber(columns[0][0])) { continue; }
var port = int.Parse(columns[1]);
switch (type)
{
case DFConstantsAndEnums.MultiCastDeviceClasses.Slice6:
if (2 != port) { continue; }
break;
case DFConstantsAndEnums.MultiCastDeviceClasses.S6DB:
if (port > 4) { continue; }
break;
}
var macAddress = columns[3];
connections.Add(new ConnectedEthernetDevice(macAddress, port));
}
return connections.ToArray();
}
private void Log(string msg)
{
if (null == Logger) { return; }
Logger.LogMessage($"====={DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}=====\r\n");
Logger.LogMessage(msg);
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"AutoDiscover: [{HostMac}] {_address} : {_port}" });
}
#endregion
#region constructors and initializers
public MulticastAutoDiscover()
: base(null)
{
Init();
}
public MulticastAutoDiscover(string macAddress)
: base(null)
{
Init(macAddress);
}
public MulticastAutoDiscover(int timeoutMillisec)
: base(null, timeoutMillisec)
{
Init();
}
public MulticastAutoDiscover(string macAddress, int timeoutMillisec)
: base(null, timeoutMillisec)
{
Init(macAddress);
}
public void Init(string macAddress = "")
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
HostMac = string.IsNullOrEmpty(macAddress) ? GetMacAddress() : macAddress;
command.SetParameter(HOST_MAC_ADDRESS_OFFSET, HostMac);
DeviceClass = DFConstantsAndEnums.MultiCastDeviceClasses.Any;
ResponseOption = ResponseOptions.AlwaysRespond;
SetMulticastConfig();
}
#endregion
}
}

View File

@@ -0,0 +1,328 @@
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Utilities.Logging;
using DTS.Common.Utils;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public abstract class MulticastCommandBase : CommandBase
{
protected const int IP_ADDR_SIZE = 16;
protected const int MAC_ADDR_SIZE = 18;
protected const int DOUBLE_MAC_ADDR_SIZE = 2 * MAC_ADDR_SIZE;
protected const int HOST_MAC_ADDRESS_OFFSET = 0;
protected const int CLIENT_MAC_ADDRESS_OFFSET = MAC_ADDR_SIZE;
protected const int FIRST_PARAMETER_OFFSET = CLIENT_MAC_ADDRESS_OFFSET + MAC_ADDR_SIZE;
protected const int DEFAULT_COMMAND_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE;
protected const int DEFAULT_RESPONSE_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE;
protected enum Commands
{
Reserved = 0x00,
AutoDiscover = 0x01,
SetIpAddress = 0x02,
GetIpAddress = 0x03,
SetSubnetAddress = 0x04,
GetSubnetAddress = 0x05,
SetGatewayAddress = 0x06,
GetGatewayAddress = 0x07,
SetDnsAddress = 0x08,
GetDnsAddress = 0x09,
SetDhcp = 0x0A,
GetDhcp = 0x0B,
ResetMcu = 0x0C,
WakeupBootloader = 0x0D,
Identify = 0x0E,
GetMACTable = 0x0F,
GetMACTable_Reserved = 0x10, // created in FW but not being used. Just ignore this command for now.
UdpQueryQTAS = 0x11, // query Arm-Trigger status via UDP multicast or unicast message via discovery route.
UdpAutoQATS = 0x12, // message command ID for auto-arm self-start UDP multicast QATS
UdpQATSInit = 0x13, // host command to send to DAS to start/stop UdpAutoQats message.
UdpAutoTiltSensorData = 0x14, //Periodic UDP response when enabled by cmd ID 0x13
UdpPrepareToShutdown = 0x15, //Command UUT to preserve auto-arm configuration and go to idle state ready for power down.
}
public enum Ports
{
Command = 8501,
Response = 8503,
}
public enum DeviceClasses
{
Unknown = 0,
Slice6 = 1 << 0,
SDB = 1 << 1,
ECM = 1 << 2,
S6DB = 1 << 3,
Slice6Air = 1 << 4,
PowerPro = 1 << 5,
TsrAir = 1 << 6,
S6DB3 = 1 << 7,
Any = 0xFFFF,
}
public enum ResponseOptions
{
AlwaysRespond = 0,
RespondIfNotBusy = 1,
RespondIfNotConnected = 2
}
public static int DEFAULT_RECEIVE_TIMEOUT_MS = 3000;
public const string DEFAULT_MULTICAST_ADDRESS = "239.1.2.3";
public const string DEFAULT_RECEIVE_ADDRESS = "239.4.5.6";
public static string MulticastAddress = DEFAULT_MULTICAST_ADDRESS;
public static string MulticastReceiveAddress = DEFAULT_RECEIVE_ADDRESS;
public static int CommandPort = (int)Ports.Command;
public static int ResponsePort = (int)Ports.Response;
protected abstract Commands Command { get; }
protected MulticastCommandBase(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.Multicast;
command.SetCommand((byte)Command, Command.ToString());
command.Parameter = new byte[DEFAULT_COMMAND_PAYLOAD_SIZE];
}
protected MulticastCommandBase(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
command.Type = CommandPacket.CommandType.Multicast;
command.SetCommand((byte)Command, Command.ToString());
command.Parameter = new byte[DEFAULT_COMMAND_PAYLOAD_SIZE];
}
public void BuildPacket()
{
baseCommand.ComputeCRCs();
}
protected virtual bool StopAfterFirstMessage => true;
public int ReceiveTimeoutMs { get; set; } = DEFAULT_RECEIVE_TIMEOUT_MS;
private string _commandHostMac;
protected string CommandClientMac;
protected string ResponseHostMac;
protected string ResponseClientMac;
public string HostMac
{
get => _commandHostMac;
set { _commandHostMac = value; command.SetParameter(HOST_MAC_ADDRESS_OFFSET, _commandHostMac); }
}
public string ClientMac { set { CommandClientMac = value; command.SetParameter(CLIENT_MAC_ADDRESS_OFFSET, CommandClientMac); } }
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
response.GetParameter(HOST_MAC_ADDRESS_OFFSET, out ResponseHostMac);
response.GetParameter(CLIENT_MAC_ADDRESS_OFFSET, out ResponseClientMac);
if (!CommandClientMac.Equals(ResponseClientMac) || !HostMac.Equals(ResponseHostMac))
{
response.Status = DFConstantsAndEnums.CommandStatus.StatusInvalidPacket;
}
return CommandReceiveAction.StopReceiving;
}
public IPAddress BindToAdapterIPAddress { get; set; } = IPAddress.Any;
private void SendRequest()
{
var txGroupAddress = IPAddress.Parse(MulticastAddress);
var remoteEndPoint = new IPEndPoint(txGroupAddress, CommandPort);
UdpClient client = null;
if (BindToAdapterIPAddress == IPAddress.Any)
{
client = new UdpClient();
}
else
{
client = new UdpClient(new IPEndPoint(BindToAdapterIPAddress, CommandPort));
}
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.IpTimeToLive, 4);
command.SequenceNumber = 0;
command.ComputeCRCs();
var data = command.ToBytes();
client.Send(data, data.Length, remoteEndPoint);
client.Close();
}
/// <summary>
/// alternative to MulticastExecute,
/// just sends the multicast request, relies on
/// StartListening to have been called to process any incoming data
/// </summary>
public void SendCommand()
{
SendRequest();
}
/// <summary>
/// used to signal Listen() function that it should terminate
/// </summary>
protected ManualResetEvent _stopListening = new ManualResetEvent(false);
/// <summary>
/// starts a listening thread
/// </summary>
public void StartListening()
{
CancellationToken ct;
Task.Run(() => ReceiveThread(null, true, ct)).ConfigureAwait(false);
}
/// <summary>
/// stops any listening thread
/// </summary>
public void StopListening() => _stopListening.Set();
public void MulticastExecute(CancellationToken ct, bool waitForResponse = true)
{
if (ct.IsCancellationRequested) { return; }
//It's easier to kick off a worker thread to handle the receiver
using (var signalComplete = new ManualResetEvent(true))
{
if (true == waitForResponse)
{
signalComplete.Reset();
Task.Run(() => ReceiveThread(signalComplete, false, ct));
//Give it time to come up
Thread.Sleep(100);
}
//Send request once receive socket is set up
SendRequest();
WaitHandle.WaitAny(new[] { signalComplete, ct.WaitHandle });
}
}
protected virtual void ProcessResponse(byte[] data)
{
response = new CommandPacket(data);
WholePackage();
}
private const int UDP_ASYNC_RESPONSETIME_MS = 1000;
/// <summary>
/// Listens for UDP responses. Can signal when complete and can listen until _stopListening MRE is set.
/// </summary>
/// <param name="signalComplete">This MRE is set when the process is complete</param>
/// <param name="listenUntilStopped">This will cause the listening loop to continue untill stopped by the _stopListening MRE</param>
private void ReceiveThread(ManualResetEvent signalComplete, bool listenUntilStopped, CancellationToken ct)
{
var rxGroupAddress = IPAddress.Parse(MulticastReceiveAddress);
var endPoint = new IPEndPoint(BindToAdapterIPAddress, ResponsePort);
var receiver = new UdpClient();
receiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
receiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, ReceiveTimeoutMs);
_stopListening.Reset();
if (BindToAdapterIPAddress == IPAddress.Any) { receiver.ExclusiveAddressUse = false; }
try
{
receiver.Client.Bind(endPoint);
}
catch (Exception ex)
{
APILogger.Log(ex);
if (!ct.IsCancellationRequested)
{
signalComplete?.Set();
}
return;
}
if (ct.IsCancellationRequested) { return; }
try
{
if (BindToAdapterIPAddress == IPAddress.Any)
{
receiver.JoinMulticastGroup(rxGroupAddress);
}
else
{
receiver.JoinMulticastGroup(rxGroupAddress, BindToAdapterIPAddress);
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
var timeToWait = TimeSpan.FromMilliseconds(UDP_ASYNC_RESPONSETIME_MS);
byte[] data = new byte[0];
IAsyncResult asyncResult = null;
do
{
if (BindToAdapterIPAddress != IPAddress.Any && !NetworkUtils.IsNetworkInterfaceUp(BindToAdapterIPAddress))
{
Thread.Sleep(100);
continue;
}
asyncResult = receiver.BeginReceive(null, null);
asyncResult.AsyncWaitHandle.WaitOne(timeToWait);
if (asyncResult.IsCompleted)
{
try
{
IPEndPoint remoteEP = null;
data = receiver.EndReceive(asyncResult, ref remoteEP);
// EndReceive worked and we have received data and remote endpoint
System.Diagnostics.Debug.WriteLine("Got " + data.Length + " bytes from " + remoteEP);
ProcessResponse(data);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
} while (!_stopListening.WaitOne(0, false) && (asyncResult == null || asyncResult.IsCompleted) && !ct.IsCancellationRequested);
receiver.Close();
if (ct.IsCancellationRequested) { return; }
if (null != signalComplete && !signalComplete.WaitOne(0))
{
signalComplete.Set();
}
}
//This is a little hokey. It returns the first interface that's multicast compatible AND 'up'. It may not actually be the interface
//that we're interested in.
public static string GetMacAddress()
{
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var i in interfaces)
{
if (OperationalStatus.Up != i.OperationalStatus || !i.SupportsMulticast) continue;
var address = BitConverter.ToString(i.GetPhysicalAddress().GetAddressBytes());
address = address.Replace("-", ":");
return address;
}
return null;
}
}
}

View File

@@ -0,0 +1,233 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using DTS.DASLib.Command.Classes;
using DTS.Common.Utilities.Logging;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Enums.DASFactory;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
/// <summary>
/// 10558 Auto-discovery to add cmd/res support for MAC table
/// </summary>
public class MulticastDiscoverSlice6 : MulticastCommandBase
{
#region constants and enums
private const int COMMAND_PAYLOAD_SIZE = 80;
private const int DEVICE_CLASS_OFFSET = 36;
private const int NUMBER_OF_RECORDS_OFFSET = 40;
private const int RESERVED_OFFSET = 42;
private const int START_OF_MAC_TABLE = 48;
private const int SIZE_OF_MAC_RECORD = 12;//bytes
private const int PORT_OFFSET = 2;
private const int FILTER_OFFSET = 4;
private const int MAC_OFFSET = 6;
#endregion
#region private properties
protected override Commands Command => Commands.GetMACTable;
protected override bool StopAfterFirstMessage => false;
private uint _deviceClass;
private byte _responseOption;
private IPAddress _address;
private const string RX_MULTICAST_ADDRESS = "239.4.5.6";
private void SetMulticastConfig()
{
IPAddress.TryParse(RX_MULTICAST_ADDRESS, out _address);
}
#endregion
#region public properties
public DeviceClasses DeviceClass { set { _deviceClass = (uint)value; command.SetParameter(36, (int)_deviceClass); } }
public ResponseOptions ResponseOption { set { _responseOption = (byte)value; command.SetParameter(40, _responseOption); } }
public uint DesiredPort
{
set => command.SetParameter(41, value);
}
public byte[] MACFilter
{
set => command.SetParameter(45, value);
}
public TextLogger Logger { get; set; }
public Dictionary<string, IDiscoveredDevice> MACAddressToDevice { get; set; }
private readonly List<DiscoveredConnectedSlice> _connectedDevices = new List<DiscoveredConnectedSlice>();
public DiscoveredConnectedSlice[] ConnectedDevices => _connectedDevices.ToArray();
#endregion
#region constructors and initializers
public MulticastDiscoverSlice6(DeviceClasses deviceClass, string hostMac)
: base(null)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
HostMac = hostMac;
DeviceClass = deviceClass;
ResponseOption = ResponseOptions.AlwaysRespond;
SetMulticastConfig();
DesiredPort = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3;
MACFilter = new[]
{
Convert.ToByte(0x00),
Convert.ToByte(0x19),
Convert.ToByte(0x9b),
byte.MaxValue,
byte.MaxValue,
byte.MaxValue
};
}
public MulticastDiscoverSlice6(string hostMac, int timeoutMillisec)
: base(null, timeoutMillisec)
{
command.Parameter = new byte[COMMAND_PAYLOAD_SIZE];
HostMac = hostMac;
DeviceClass = DeviceClasses.Any;
ResponseOption = ResponseOptions.AlwaysRespond;
SetMulticastConfig();
DesiredPort = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3;//ports 1-4
MACFilter = new[]
{
Convert.ToByte(0x00),
Convert.ToByte(0x19),
Convert.ToByte(0x9b),
byte.MaxValue,
byte.MaxValue,
byte.MaxValue
};
}
#endregion
#region methods
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
response.GetParameter(HOST_MAC_ADDRESS_OFFSET, out ResponseHostMac);
if (null == ResponseHostMac || !HostMac.Equals(ResponseHostMac))
{
response.Status = DFConstantsAndEnums.CommandStatus.StatusInvalidPacket;
return CommandReceiveAction.StopReceiving;
}
response.GetParameter(CLIENT_MAC_ADDRESS_OFFSET, out ResponseClientMac);
response.GetParameter(DEVICE_CLASS_OFFSET, out _deviceClass);
ushort numberOfEntries;
response.GetParameter(NUMBER_OF_RECORDS_OFFSET, out numberOfEntries);
var list = new List<MACTableEntry>();
for (var i = 0; i < numberOfEntries; i++)
{
try
{
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD, out ushort age);
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD + PORT_OFFSET, out ushort port);
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD + FILTER_OFFSET, out ushort filter);
var mac = new byte[6];
for (var b = 0; b < mac.Length; b++)
{
response.GetParameter(START_OF_MAC_TABLE + i * SIZE_OF_MAC_RECORD + MAC_OFFSET + b, out byte thisByte);
mac[b] = thisByte;
}
list.Add(new MACTableEntry(age, port, filter, mac));
}
catch (Exception ex)
{
APILogger.Log($"MulticastDiscoverSlice6 failed to get entry - ignoring entry", ex.Message);
}
}
_connectedDevices.Add(new DiscoveredConnectedSlice(ResponseClientMac, list.ToArray()));
var responseMac = ResponseClientMac.Replace('-', ':').ToUpper();
var serialNumber = "N/A";
if (null != MACAddressToDevice && MACAddressToDevice.ContainsKey(responseMac))
{
serialNumber = MACAddressToDevice[responseMac].Serial;
}
Log(ResponseHostMac, ResponseClientMac, list.ToArray(), serialNumber);
//Log(response.Parameter);
return CommandReceiveAction.StopReceiving;
}
private static string ByteToHex(byte b)
{
return $"{b:x2}";
}
private void Log(IReadOnlyList<byte> parameter)
{
var sb = new StringBuilder();
sb.Append("msg: ");
foreach (var b in parameter)
{
sb.Append(ByteToHex(b));
}
sb.AppendLine();
//var bytes = new List<byte>(parameter);
sb.Append("header: ");
for (var i = 0; i < START_OF_MAC_TABLE; i++)
{
sb.Append(ByteToHex(parameter[i]));
}
sb.AppendLine();
for (var i = START_OF_MAC_TABLE; i < parameter.Count; i += SIZE_OF_MAC_RECORD)
{
sb.Append("Record: ");
for (var idx = 0; idx < SIZE_OF_MAC_RECORD; idx++)
{
sb.Append(ByteToHex(parameter[i + idx]));
}
sb.AppendLine();
}
Log(sb.ToString());
}
private void Log(string responseHostMac, string responseClientMac, MACTableEntry[] entries, string serialNumber)
{
var sb = new StringBuilder();
sb.AppendFormat("Host: {0}, Client: {1}, SerialNumber: {2}", responseHostMac, responseClientMac, serialNumber);
sb.AppendLine();
sb.AppendLine("Age\tFilter\tMAC\t\t\tPort");
foreach (var entry in entries)
{
sb.AppendFormat("{0}\t{1}\t{2}\t{3}", entry.Age, entry.Filter, MACAddressToString(entry.MAC), entry.Port);
sb.AppendLine();
}
Log(sb.ToString());
}
public static string MACAddressToString(IEnumerable<byte> mac)
{
var list = mac.Select(b => $"{b:x2}").ToList();
return string.Join(":", list.ToArray()).ToUpper();
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"AutoDiscover: [{HostMac}]" });
}
private void Log(string msg)
{
if (null == Logger) { return; }
Logger.LogMessage($"====={DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}=====\r\n");
Logger.LogMessage(msg);
}
#endregion
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastGetDhcp : MulticastCommandBase
{
protected override Commands Command => Commands.GetDhcp;
private byte _dhcp;
public bool Dhcp => Convert.ToBoolean(_dhcp);
public MulticastGetDhcp(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public MulticastGetDhcp(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
return CommandReceiveAction.StopReceiving;
base.WholePackage();
response.GetParameter(FIRST_PARAMETER_OFFSET, out _dhcp);
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {ResponseClientMac} " });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string> { $"MAC: {ResponseClientMac} Dhcp: {_dhcp}" });
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastGetDnsAddress : MulticastCommandBase
{
protected override Commands Command => Commands.GetDnsAddress;
private string _dns;
public string Dns => _dns;
public MulticastGetDnsAddress(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public MulticastGetDnsAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
base.WholePackage();
response.GetParameter(FIRST_PARAMETER_OFFSET, out _dns);
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} " });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} Dns: {_dns}" });
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
namespace DTS.DASLib.Command.SLICE.MulticastCommands
{
public class MulticastGetGatewayAddress : MulticastCommandBase
{
protected override Commands Command => Commands.GetGatewayAddress;
private string _gateway;
public string Gateway => _gateway;
public MulticastGetGatewayAddress(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public MulticastGetGatewayAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
: base(sock, timeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
base.WholePackage();
response.GetParameter(FIRST_PARAMETER_OFFSET, out _gateway);
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} " });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string> { $"MAC: {CommandClientMac} Gateway: {_gateway}" });
}
}
}

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