Files
DP44/DataPRO/SLICECommands/InformationCommands.cs

1297 lines
46 KiB
C#
Raw Normal View History

2026-04-17 14:55:32 -04:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTS.Common.DASResource;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Utilities;
namespace DTS.DASLib.Command.SLICE
{
/* from firmware
* typedef struct _tFirmwareFileHeader
{
// file format: totalLen = firmwaresize + 108B header.
uint16_t magicNum; // 2 2 marker: 0x1234
uint16_t headerCRC16; // 2 4 crc16 for header
uint32_t fileLen; // 4 8 firmwaresize in originaltxt format + header size
uint16_t formatType; // 2 10 0 = text. other TBD.
uint16_t fileCRC16; // 2 12 crc16 for firmware in txt format.
uint16_t binCRC16; // 2 14 TBD crc16 for extracted bin format.
uint16_t reserved[7]; // 14 28 TBD.
uint8_t data[80]; // 80 108 any note from host. Filename for example...
} tFirmwareFileHeader;
*/
public struct SliceProFirmwareImageHeader
{
// file format: totalLen = firmwaresize + 108B header.
public ushort magicNum; // 2 2 marker: 0x1234
public ushort headerCRC16; // 2 4 crc16 for header
public uint fileLen; // 4 8 firmwaresize in originaltxt format + header size
public ushort formatType; // 2 10 0 = text. other TBD.
public ushort fileCRC16; // 2 12 crc16 for firmware in txt format.
public ushort binCRC16; // 2 14 TBD crc16 for extracted bin format.
public ushort[] reserved; // 14 28 TBD.
public byte[] data; // 80 108 any note from host. Filename for example...
}
public abstract class InformationCommands : CommandBase
{
protected enum Commands
{
Reserved = 0x00,
QueryStackContents = 0x01,
QueryProtocolVersion = 0x02,
QueryGroup = 0x03,
SetGroup = 0x04,
QueryFirmwareVersion = 0x05,
QuerySerialNumber = 0x06,
SetSerialNumber = 0x07,
QueryType = 0x08,
QueryOneWireID = 0x09,
QueryOneWireEEPROM = 0x0A,
SetOneWireEEPROM = 0x0B,
QueryMSP430FirmwareVersion = 0x0C,
SetFileData = 0x0D,
QueryFileData = 0x0E,
QueryFirmwareBuildVersion = 0x0F,
QueryStackSensorIDs = 0x10, // new command after protocol 136 to query all sensor IDs on stack.
SetStackInfoData = 0x11, // TBD. Not yet implemented. set 64-byte data block to infoB page.
QueryStackInfoData = 0x12, // TBD. Not yet implemented. query 64-byte data block from infoB page.
QueryFirmwareBuildID = 0x13, // TBD. Now supporting via system attribute. query build information from slice.
QueryBaseSystemTime = 0x14, // query current system time: sec.min.hr.days.weekdays.years (from 20xx)
SetBaseSystemTime = 0x15, // set current system time: sec.min.hr.days.weekdays.years (from 20xx)
QueryTempLogFile = 0x16,
};
//100 is now the max, per 14531 Implement TMATS support for S6A stream on boot
protected const int MAX_FILE_ID = 100; // user = 10, firmware = 20, max internally = 65. 10;
protected const int MAX_FILE_LENGTH = 400;
public const int MAX_FILE_LENGTH_ID100 = 16000;
protected const int MAX_FILE_READ_LENGTH = 1024;
protected abstract Commands _Command
{
get;
}
protected InformationCommands(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Type = CommandPacket.CommandType.Information;
command.SetCommand((byte)_Command, _Command.ToString());
}
protected InformationCommands(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Type = CommandPacket.CommandType.Information;
command.SetCommand((byte)_Command, _Command.ToString());
}
}
public class QueryStackContents : InformationCommands
{
const int SliceDescriptorSize = 24;
const int AddressPosition = 0;
const int GroupPosition = 1;
const int TypePosition = 2;
const int SerialNumberPosition = 3;
const int FirmwareVersionPosition = 19;
public int SliceCount { get; private set; } = 0;
public string[] SerialNumber { get; private set; }
public string[] FirmwareVersion { get; private set; }
public byte[] SliceType { get; private set; }
public byte[] SliceAddress { get; private set; }
public byte[] SliceGroup { get; private set; }
protected override Commands _Command => Commands.QueryStackContents;
public QueryStackContents(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryStackContents(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
// we have a whole package
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
SliceCount = response.ParameterLength / SliceDescriptorSize;
SerialNumber = new string[SliceCount];
FirmwareVersion = new string[SliceCount];
SliceType = new byte[SliceCount];
SliceAddress = new byte[SliceCount];
SliceGroup = new byte[SliceCount];
for (int i = 0; i < SliceCount; i++)
{
response.GetParameter(SliceDescriptorSize * i + AddressPosition, out SliceAddress[i]);
response.GetParameter(SliceDescriptorSize * i + GroupPosition, out SliceGroup[i]);
response.GetParameter(SliceDescriptorSize * i + TypePosition, out SliceType[i]);
response.GetParameter(SliceDescriptorSize * i + SerialNumberPosition, out SerialNumber[i]);
response.GetParameter(SliceDescriptorSize * i + FirmwareVersionPosition, out FirmwareVersion[i]);
}
}
else
{
SliceCount = 0;
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"SliceCount: {SliceCount}",
$"Connection: {recorder.ConnectString}"
});
for (int i = 0; i < SliceCount; i++)
{
var line = new List<string>();
line.Add($"Serial Number: {(SerialNumber != null && SerialNumber.Length > 0 ? SerialNumber[i] : "<null>")}, ");
line.Add($"Firmware version: {(FirmwareVersion != null && FirmwareVersion.Length > 0 ? FirmwareVersion[i] : "<null>")}, ");
line.Add($"Type: {(SliceType != null ? ((ChannelTypes)SliceType[i]).ToString() : "<null>")}, ");
line.Add($"Address: {(SliceAddress != null ? SliceAddress[i].ToString() : "<null>")}, ");
line.Add($"Group: {(SliceGroup != null ? SliceGroup[i].ToString() : "<null>")}");
lines.Add(line);
}
}
}
public class QueryProtocolVersion : InformationCommands
{
private byte _versionbyte = 0;
public byte Version => _versionbyte;
protected override Commands _Command => Commands.QueryProtocolVersion;
public QueryProtocolVersion(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryProtocolVersion(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
// we have a whole package
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _versionbyte);
}
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 QueryFirmwareVersion : InformationCommands
{
string _versionstring = string.Empty;
public string Version => _versionstring;
protected override Commands _Command => Commands.QueryFirmwareVersion;
public QueryFirmwareVersion(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryFirmwareVersion(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
// we have a whole package
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _versionstring);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { Version });
}
}
public class QuerySerialNumber : InformationCommands
{
private string _serialnumber = string.Empty;
public string SerialNumber => _serialnumber;
protected override Commands _Command => Commands.QuerySerialNumber;
public QuerySerialNumber(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QuerySerialNumber(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
// we have a whole package
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _serialnumber);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"SerialNumber: {SerialNumber}" });
}
}
public class SetSerialNumber : InformationCommands
{
private string _sn = string.Empty;
protected override Commands _Command => Commands.SetSerialNumber;
public string SerialNumber
{
get => _sn;
set
{
_sn = value;
command.Parameter = new byte[value.Length + 1];
command.SetParameter(0, value.ToCharArray());
}
}
public SetSerialNumber(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public SetSerialNumber(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>() { $"SerialNumber: {SerialNumber}" });
}
}
public class QueryOneWireID : InformationCommands
{
private const int StackChannelPosition = 0;
private const int OneWireIDLength = 8;
protected override Commands _Command => Commands.QueryOneWireID;
public List<byte[]> IDs { get; private set; } = new List<byte[]>();
private byte _stackchannel;
public byte StackChannel
{
get => _stackchannel;
set
{
_stackchannel = value;
command.SetParameter(StackChannelPosition, _stackchannel);
}
}
private bool _bSupportsIdTypes = false;
public enum IdTypes
{
Default = 0x0,
Bridge = 0x1,
IEPE = 0x2
};
private IdTypes _idType = IdTypes.Default;
public IdTypes IdType
{
get => _idType;
set
{
if (_bSupportsIdTypes)
{
_idType = value;
command.SetParameter(1, (byte)value);
}
}
}
public QueryOneWireID(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
if (sock.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.SLICE2_OneWireID))
{
command.Parameter = new byte[2];
_bSupportsIdTypes = true;
}
else { command.Parameter = new byte[1]; }
}
public QueryOneWireID(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
if (sock.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.SLICE2_OneWireID))
{
command.Parameter = new byte[2];
_bSupportsIdTypes = true;
}
else { command.Parameter = new byte[1]; }
}
protected override CommandReceiveAction WholePackage()
{
// we have a whole package
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
int numberOfIDs = response.ParameterLength / OneWireIDLength;
IDs = new List<byte[]>();
for (int i = 0; i < numberOfIDs; i++)
{
var id = new byte[OneWireIDLength];
var reversedId = new byte[OneWireIDLength];
Buffer.BlockCopy(response.Parameter, OneWireIDLength * i, reversedId, 0, OneWireIDLength);
for (int currentByte = reversedId.Length - 1; currentByte >= 0; currentByte--)
{
id[OneWireIDLength - currentByte - 1] = reversedId[currentByte];
}
IDs.Add(id);
}
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>() { $"Stack Channel: {StackChannel}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"Number of IDs: {IDs.Count}"
});
var ids = new List<string>();
for (int i = 0; null != IDs && i < IDs.Count; i++)
{
if (0 == i) { ids.Add($"IDS: {HexEncoding.ToString(IDs[i])}"); }
else { ids.Add(HexEncoding.ToString(IDs[i])); }
}
if (ids.Count > 0)
{
lines.Add(ids);
}
}
}
public class QueryMSP430FirmwareVersion : InformationCommands
{
private string _versionstring = string.Empty;
public string Version => _versionstring;
protected override Commands _Command => Commands.QueryMSP430FirmwareVersion;
public QueryMSP430FirmwareVersion(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public QueryMSP430FirmwareVersion(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
}
protected override CommandReceiveAction WholePackage()
{
// we have a whole package
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
response.GetParameter(0, out _versionstring);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { Version });
}
}
/// <summary>
/// Command ID 0x0D Information FILE Data Set
/// STU shall accept data from USER and save to file ID indicated in message.
/// </summary>
public class SetFileData : InformationCommands
{
protected override Commands _Command => Commands.SetFileData;
#region Private Variables
private 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 ushort FileID
{
get => _fileID;
set
{
if (MAX_FILE_ID < value)
{
throw new NotSupportedException($"FileId: {value.ToString()} > {MAX_FILE_ID.ToString()}");
}
_fileID = value;
command.SetParameter(0, _fileID);
}
}
public uint StartByteCount
{
get => _startByteCount;
set { _startByteCount = value; command.SetParameter(2, _startByteCount); }
}
/// <summary>
/// This is the TMT file ID, per 14531 Implement TMATS support for S6A stream on boot
/// </summary>
public const ushort TMT_FILE_ID = 100;
public byte[] Data
{
get => _data;
set
{
if (null == value)
{
return;
}
var maxLength = MAX_FILE_LENGTH;
if (FileID == TMT_FILE_ID)
{
maxLength = MAX_FILE_LENGTH_ID100;
if (recorder is ITMATSStreamingDevice tmatsStreamer)
{
maxLength = tmatsStreamer.GetMaxFileLengthTMATS();
}
}
if (maxLength < value.Length)
{
throw new ArgumentOutOfRangeException($"File length: {value.Length} > {maxLength.ToString()}");
}
_data = value;
//if (this.command.Parameter.Length < value.Length+ PARAM_NUM)
//{
var 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 SetFileData(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[PARAM_NUM];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.FileData);
_data = null;
_fileID = 0;
_startByteCount = 0;
command.ShouldLog = false;
}
public SetFileData(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[PARAM_NUM];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.FileData);
_data = null;
_fileID = 0;
_startByteCount = 0;
command.ShouldLog = false;
}
#endregion
#region Log Functions
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>() { $"Store ID: {FileID}, Start Byte: {StartByteCount}, End Byte: {Size + StartByteCount}" });
}
public void LogResponse()
{
LogCommand(false);
}
#endregion
}
/// <summary>
/// Command ID 0x0E Information FILE Data Query
/// STU shall respond with data requested by host similar to download process.
/// </summary>
public class QueryFileData : InformationCommands
{
protected override Commands _Command => Commands.QueryFileData;
#region Private Variables
private ushort _fileID; //Byte 0-1: 16-bit file ID ranges from 1-10.
private uint _startByteCount; //Byte 2-5: 32-bit StartBytecount which ranges from 0 to EndBytecount
private uint _endByteCount; //Byte 6-9: 32-bit EndBytecount.
#endregion
#region Command Parameters
public ushort FileID
{
get => _fileID;
set
{
if (MAX_FILE_ID < value)
{
throw new ArgumentOutOfRangeException($"FileId {value.ToString()} > {MAX_FILE_ID.ToString()}");
}
_fileID = value;
command.SetParameter(0, _fileID);
}
}
public uint StartByteCount
{
get => _startByteCount;
set { _startByteCount = value; command.SetParameter(2, _startByteCount); }
}
public uint EndByteCount
{
get => _endByteCount;
set { _endByteCount = value; command.SetParameter(6, _endByteCount); }
}
#endregion
#region Command Variables
public uint BytesDownloaded { get; set; }
public byte[] Data { get; private set; }
public int MaximumFileStreamBytes => MAX_FILE_LENGTH;
public int MaxFileReadStreamBytes => MAX_FILE_READ_LENGTH;
#endregion
#region Command Functions
public QueryFileData(Common.Interface.DASFactory.ICommunication sock) : base(sock)
{
command.Parameter = new byte[10];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.FileData);
Data = null;
_fileID = 0;
_startByteCount = 0;
_endByteCount = 0;
command.ShouldLog = false;
}
public QueryFileData(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec) : base(sock, TimeoutMillisec)
{
command.Parameter = new byte[10];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.FileData);
Data = null;
_fileID = 0;
_startByteCount = 0;
_endByteCount = 0;
command.ShouldLog = false;
}
protected override CommandReceiveAction WholePackage()
{
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
return CommandReceiveAction.StopReceiving;
}
BytesDownloaded = (uint)(response.Parameter.Length);
Data = new byte[BytesDownloaded];
for (int i = 0; (uint)i < BytesDownloaded; i++)
{
response.GetParameter(i, out Data[i]);
}
return CommandReceiveAction.StopReceiving;
}
public override void SyncExecute()
{
// Do a little parameter checking
if (_startByteCount > _endByteCount)
{
// "QueryEventData.SyncExecute: First Sample cannot be greater than Last Sample"
throw new ApplicationException(Strings.QueryEventData_SyncExecute_Err1);
}
base.SyncExecute();
}
#endregion
#region Log Functions
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>() { $"Store ID: {FileID}, Start Byte: {StartByteCount}, End Byte: {EndByteCount}" });
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"Store ID: {FileID}, BytesDownloaded: {BytesDownloaded}"
});
}
public void LogResponse()
{
LogCommand(false);
}
#endregion
}
public class QueryStackSensorIDs : InformationCommands
{
private const byte StackChannelPosition = 0;
private const byte ParameterLength = 1;
private const byte ChannelDataLength = 10;
private const byte IDLength = 8;
private const byte TypeIndex = 9;
private const byte ChannelIndex = 10;
protected override Commands _Command => Commands.QueryStackSensorIDs;
public List<byte[]> IDs { get; private set; } = new List<byte[]>();
public List<byte> Types { get; private set; } = new List<byte>();
public List<byte> Channels { get; private set; } = new List<byte>();
private byte _stackchannel;
public byte StackChannel
{
get => _stackchannel;
set
{
_stackchannel = value;
command.SetParameter(StackChannelPosition, _stackchannel);
}
}
public QueryStackSensorIDs(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[ParameterLength];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackSensors);
}
public QueryStackSensorIDs(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[ParameterLength];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.StackSensors);
}
public void Exec()
{
SyncExecute();
}
protected override CommandReceiveAction WholePackage()
{
// we have a whole package
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
int numberOfIDs = response.ParameterLength / ChannelDataLength;
IDs = new List<byte[]>();
Types = new List<byte>();
Channels = new List<byte>();
for (int i = 0; i < numberOfIDs; i++)
{
var data = new byte[ChannelDataLength];
var reversed_data = new byte[ChannelDataLength];
var id = new byte[IDLength];
var type = new byte();
var channel = new byte();
Buffer.BlockCopy(response.Parameter, ChannelDataLength * i, reversed_data, 0, ChannelDataLength);
for (int currentByte = reversed_data.Length - 1; currentByte >= 0; currentByte--)
{
data[ChannelDataLength - currentByte - 1] = reversed_data[currentByte];
}
for (int currentByte = 0; currentByte < data.Length; currentByte++)
{
if (currentByte < IDLength)
{
id[currentByte] = data[currentByte];
}
else if (currentByte < TypeIndex)
{
type = data[currentByte];
}
else
{
channel = data[currentByte];
}
}
IDs.Add(id);
Types.Add(type);
Channels.Add(channel);
}
}
return CommandReceiveAction.StopReceiving;
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>()
{
$"Stack Channel: {StackChannel}"
});
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>()
{
$"Number of Stack Channels: {Channels.Count}"
});
var info = new List<string>();
for (int i = 0; null != IDs && i < IDs.Count; i++)
{
info.Add($"Channel: {Channels[i].ToString()}, Type {Types[i].ToString()}, IDS: {HexEncoding.ToString(IDs[i])}");
}
if (info.Count > 0)
{
lines.Add(info);
}
}
}
public class QueryBaseSystemTime : InformationCommands
{
public byte[] Calendar { get; } = new byte[7];
private DateTime _systemTime = DateTime.MinValue;
public DateTime SystemTime
{
get
{
if (_systemTime == DateTime.MinValue)
{
var cal = new byte[7];
for (int i = 0; i < cal.Length; i++)
{
cal[i] = Calendar[i];
}
// convert from BCD to binary
uint dec, dec2;
for (int i = 0; i < 7; i++)
{
dec = (uint)cal[i] & 0x0f;
dec2 = (uint)cal[i] >> 4;
dec2 = dec2 * 10;
dec = dec + dec2;
cal[i] = (byte)dec;
}
_systemTime = new DateTime(cal[6] + 2000, // year
cal[5], // month
cal[3], // day
cal[2], // hh
cal[1], // mm
cal[0]); // ss
}
return _systemTime;
}
}
protected override Commands _Command => Commands.QueryBaseSystemTime;
public QueryBaseSystemTime(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime);
}
public QueryBaseSystemTime(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime);
}
protected override CommandReceiveAction WholePackage()
{
// we have a whole package
if (response.Status == DFConstantsAndEnums.CommandStatus.StatusNoError)
{
for (int i = 0; i < 7; i++)
{
response.GetParameter(i, out Calendar[i]);
}
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"System Time: {SystemTime}" });
}
}
public class SetBaseSystemTime : InformationCommands
{
private DateTime _systemTime = new DateTime();
protected override Commands _Command => Commands.SetBaseSystemTime;
public DateTime SystemTime
{
get => _systemTime;
set
{
var timestream = new byte[7];
timestream[0] = (byte)value.Second;
timestream[1] = (byte)value.Minute;
timestream[2] = (byte)value.Hour;
timestream[3] = (byte)value.Day;
timestream[4] = (byte)value.DayOfWeek;
timestream[5] = (byte)value.Month;
timestream[6] = (byte)(value.Year - 2000);
// convert binary to BCD
uint bcd, bcd2;
for (int i = 0; i < 7; i++)
{
bcd = ((uint)timestream[i]) / 10;
bcd2 = ((uint)timestream[i]) % 10;
bcd = (bcd << 4) + bcd2;
timestream[i] = (byte)bcd;
}
command.Parameter = timestream;
_systemTime = value;
}
}
public SetBaseSystemTime(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime);
}
public SetBaseSystemTime(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime);
}
public override void CommandToString(ref List<List<string>> lines)
{
base.CommandToString(ref lines);
lines.Add(new List<string>()
{
$"System Time: {SystemTime}"
});
}
}
/*
* cmdInfo_queryTempLogfile - query tempurature logfile in S6DB
*
* @param
* uint8_t cmd. No param or param value = 0. Readonly. 1 = readclear.
* uint8_t u8-rsv; // for future subcommand.
* uint32_t time offset from the current time in second.
* uint32_t timeROI in second.
* for example:
* u8 cmd = 0.
* u8 rsv. Maybe sampleByteSize;
* u32 timeOffset = 0. Start from last sample taken.
* u32 timeDurationSec = 120. Asking for sample in last two hours.
*
* @return Response status with logging data in payload.
* Data structure in payload.
* - u32 timeOffset; // confirmed with software command.
* // samplePeriodInSec can be tracked with system attr.
* // channelMask can be tracked with system attribute.
* - Repeated structure of following:
* {
* . uint32_t RTC Timestamp-Second.
* . float32_t temp1;
* . float32_t temp2;
* }
*
* Note: Default of 2 ADC channel.
* 48hr*60min/hr
**/
public class QueryTempLogFile : InformationCommands
{
//private const byte ParameterLength = 1;
uint _timeOffsetSec = 0;
uint _timeDurationSec = 48 * 60 * 60; // full log
byte _readClear = 0;
byte _rsvCmd = 0;
public uint TimeOffsetFromNowSec
{
get => _timeOffsetSec;
set
{
_timeOffsetSec = value;
command.SetParameter(2, _timeOffsetSec);
}
}
public uint TimeDurationSec
{
get => _timeDurationSec;
set
{
_timeDurationSec = value;
command.SetParameter(6, _timeDurationSec);
}
}
public byte ReadClear
{
get => _readClear;
set
{
_readClear = value;
command.SetParameter(0, _readClear);
}
}
public byte ReadRsvCmd
{
get => _rsvCmd;
set
{
_rsvCmd = value;
command.SetParameter(1, _rsvCmd);
}
}
protected override Commands _Command => Commands.QueryTempLogFile;
public QueryTempLogFile(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[10];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.QueryTempLogFile);
}
public QueryTempLogFile(Common.Interface.DASFactory.ICommunication sock, int TimeoutMillisec)
: base(sock, TimeoutMillisec)
{
command.Parameter = new byte[10];
MinimumProtocolVersion = sock.GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands.QueryTempLogFile);
}
public static DateTime UnixTimeStampToDateTime(uint unixTimeStamp)
{
// Unix timestamp is seconds past epoch
DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
return dtDateTime;
}
public List<Tuple<DateTime, double, double, uint>> TempData = new List<Tuple<DateTime, double, double, uint>>();
protected override CommandReceiveAction WholePackage()
{
// we have a whole package
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError
|| response.ParameterLength == 0) return CommandReceiveAction.StopReceiving;
response.GetParameter(2, out int dataOffset);
var sampleCount = (response.ParameterLength - 6) / 12;
uint curTicks;
float channel1Sample;
float channel2Sample;
for (int i = 6; i < response.ParameterLength - 6; i += 12)
{
response.GetParameter(i + 0, out curTicks);
response.GetParameter(i + 4, out channel1Sample);
response.GetParameter(i + 8, out channel2Sample);
TempData.Add(new Tuple<DateTime, double, double, uint>(UnixTimeStampToDateTime(curTicks).ToLocalTime(), channel1Sample, channel2Sample, curTicks));
}
TempData = TempData.OrderBy(a => a.Item1).ToList();
// check to see if any dates are bogus
var badDates = TempData.Where(x => x.Item1.Year < 1990).Select(x => x.Item1).ToList();
if (badDates.Count == 1)
{
// fix the single date
TempData[0] = TempDataReplaceDate(TempData[0], DateTime.Now - new TimeSpan(0, 1, 0));
}
else if (badDates.Count > 1)
{
// we need to extrapolate from a known good time stamp
var goodDate = DateTime.Now;
// lets see how far back our data should go
var lastBadSpan = badDates[badDates.Count - 1] - badDates[badDates.Count - 2];
var badDateTimeSpan = badDates.Last() - badDates[0] + lastBadSpan;
if (TempData.Exists(x => x.Item1.Year > 1990))
{
// if we have a good date, use it to seed the bad date extrapolation
goodDate = TempData.Where(x => x.Item1.Year > 1990).Select(x => x.Item1).ToList()[0];
}
// Fix the first data point
TempData[0] = TempDataReplaceDate(TempData[0], goodDate - badDateTimeSpan);
// Fix all the data points in between
for (int i = 1; i < TempData.Select(x => x.Item1).ToList().IndexOf(badDates.Last()); i++)
{
TempData[i] = TempDataReplaceDate(TempData[i], TempData[i - 1].Item1 + (TempData[i + 1].Item1 - TempData[i].Item1));
}
// fix the last data point
var indesxOfLastBadDate = TempData.Select(x => x.Item1).ToList().IndexOf(badDates.Last());
TempData[indesxOfLastBadDate] = TempDataReplaceDate(TempData[indesxOfLastBadDate], goodDate - lastBadSpan);
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { $"QueryTempLogFile: From:{TimeOffsetFromNowSec}s Duration:{TimeDurationSec}s Samples Returned: {TempData.Count}" });
}
/// <summary>
/// Only replaces the new date and returns the rest of the tuple for the temp log point
/// </summary>
/// <param name="origTuple"></param>
/// <param name="dateTime"></param>
/// <returns></returns>
private Tuple<DateTime, double, double, uint> TempDataReplaceDate(Tuple<DateTime, double, double, uint> origTuple, DateTime dateTime)
{
return new Tuple<DateTime, double, double, uint>(dateTime, origTuple.Item2, origTuple.Item3, origTuple.Item4);
}
}
public class QueryEeprom : InformationCommands
{
private byte _eeprom_id = 0;
private ushort _data_offset = 0;
private ushort _data_length = 0;
private byte[] _data;
public byte ID
{
set
{
_eeprom_id = value;
command.SetParameter(0, value);
}
get => _eeprom_id;
}
public ushort Data_Offset
{
get => _data_offset;
set
{
_data_offset = value;
command.SetParameter(1, _data_offset);
}
}
public ushort DataLength
{
get => _data_length;
set
{
_data_length = value;
command.SetParameter(3, _data_length);
}
}
public byte[] Data
{
set => _data = value;
get => _data;
}
protected override Commands _Command => Commands.QueryOneWireEEPROM;
public QueryEeprom(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
command.Parameter = new byte[5];
}
public QueryEeprom(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)
{
response.GetParameter(0, out _eeprom_id);
response.GetParameter(1, out _data_offset);
response.GetParameter(3, out _data_length);
_data = new byte[_data_length];
for (int i = 0; i < _data_length; i++)
{
response.GetParameter(5 + i, out _data[i]);
}
}
return CommandReceiveAction.StopReceiving;
}
public override void ResponseToString(ref List<List<string>> lines)
{
base.ResponseToString(ref lines);
lines.Add(new List<string>() { string.Format("Data: {0}", Encoding.UTF8.GetString(_data)) });
}
}
public class SetEeprom : InformationCommands
{
private byte _eeprom_id = 0;
private ushort _data_offset = 0;
private ushort _data_length = 0;
private string _data = string.Empty;
protected override Commands _Command => Commands.SetOneWireEEPROM;
public byte ID
{
set => _eeprom_id = value;
get => _eeprom_id;
}
public ushort Data_Offset
{
get => _data_offset;
set => _data_offset = value;
}
public ushort DataLength
{
get => _data_length;
set => _data_length = value;
}
public string Data
{
set => _data = value;
get => _data;
}
public void SetEEPROM()
{
command.Parameter = new byte[6 + _data_length];
for (int i = 0; i < _data_length; i++)
{
command.SetParameter(5 + i, _data[i]);
}
command.SetParameter(0, _eeprom_id);
command.SetParameter(1, _data_offset);
command.SetParameter(3, _data_length);
}
public SetEeprom(Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
}
public SetEeprom(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>() { string.Format("Data: {0}", _data) });
}
}
}