Files
DP44/DataPRO/SLICECommands/InformationCommands.cs
2026-04-17 14:55:32 -04:00

1297 lines
46 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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) });
}
}
}