393 lines
16 KiB
C#
393 lines
16 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using DTS.Common.Enums.DASFactory;
|
|
using DTS.Common.Utilities.Logging;
|
|
using DTS.Common.Utils;
|
|
|
|
namespace DTS.DASLib.Command
|
|
{
|
|
/// <summary>
|
|
/// this is the base for all slice command packets
|
|
/// from here SliceDb and slice command packets will have different commands that can be
|
|
/// run and a different command type enum containing the command types, however
|
|
/// this class contains the common logic for addressing and packing the packet
|
|
/// </summary>
|
|
public abstract class SliceCommandPacketBase : CommandPacketBase
|
|
{
|
|
public const byte MAGIC_BYTE = 0xFA;
|
|
protected const int HEADER_SIZE_BYTES = 12;
|
|
protected const int DATA_CRC_SIZE_BYTES = 2;
|
|
// Packet format -- all are 8 bits, but ParameterLength, SequenceNumber and HeaderCRC
|
|
protected const int MagicBytePosition = 0;
|
|
protected const int TypePosition = 1;
|
|
protected const int CommandPosition = 2;
|
|
protected const int StatusPosition = 3;
|
|
protected const int DeviceGroupPosition = 4;
|
|
protected const int DeviceIDPosition = 5;
|
|
// Parameter length is 16 bits
|
|
protected const int ParameterLengthPosition = 6;
|
|
// Sequence number length is 16 bits
|
|
protected const int SequenceNumberPosition = 8;
|
|
// Header CRC is 16 bits
|
|
protected const int HeaderCRCPosition = 10;
|
|
public UInt16 ParameterLength;
|
|
public byte DeviceGroup;
|
|
public byte DeviceID;
|
|
public UInt16 HeaderCRC;
|
|
public byte[] Parameter;
|
|
public UInt16 ParameterCRC;
|
|
|
|
public SliceCommandPacketBase()
|
|
{
|
|
Parameter = new byte[0];
|
|
AlreadyRun = false;
|
|
ShouldLog = true;
|
|
GetNextSequenceNumber();
|
|
}
|
|
|
|
public SliceCommandPacketBase(byte[] Bytes)
|
|
{
|
|
OriginalBytes = Bytes;
|
|
ShouldLog = true;
|
|
|
|
if (HEADER_SIZE_BYTES <= Bytes.Length && MAGIC_BYTE == Bytes[0])
|
|
{
|
|
Type = ConvertByteToCommandType(Bytes[TypePosition]);//(CommandType)Bytes[TypePosition];
|
|
//Command = Bytes[CommandPosition];
|
|
SetCommand(Bytes[CommandPosition], Convert.ToString(Bytes[CommandPosition]));
|
|
Status = (DFConstantsAndEnums.CommandStatus)Bytes[StatusPosition];
|
|
DeviceGroup = Bytes[DeviceGroupPosition];
|
|
DeviceID = Bytes[DeviceIDPosition];
|
|
ParameterLength = (ushort)(Bytes[ParameterLengthPosition + 0] |
|
|
(Bytes[ParameterLengthPosition + 1] << 8));
|
|
SequenceNumber = (ushort)(Bytes[SequenceNumberPosition + 0] |
|
|
(Bytes[SequenceNumberPosition + 1] << 8));
|
|
HeaderCRC = (ushort)(Bytes[HeaderCRCPosition + 0] |
|
|
(Bytes[HeaderCRCPosition + 1] << 8));
|
|
|
|
Parameter = new byte[ParameterLength];
|
|
|
|
if (ParameterLength > 0 && Bytes.Length > HEADER_SIZE_BYTES)
|
|
{
|
|
try
|
|
{
|
|
Buffer.BlockCopy(Bytes, HEADER_SIZE_BYTES + DATA_CRC_SIZE_BYTES, Parameter, 0, ParameterLength);
|
|
|
|
ParameterCRC = (UInt16)(Bytes[HEADER_SIZE_BYTES + 0] |
|
|
Bytes[HEADER_SIZE_BYTES + 1] << 8);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log(ex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override PacketState VerifyPacket(byte[] Bytes)
|
|
{
|
|
if (Bytes == null)
|
|
return PacketState.Unknown;
|
|
|
|
if (Bytes.Length < HEADER_SIZE_BYTES)
|
|
return PacketState.TooShort;
|
|
|
|
if (Bytes[MagicBytePosition] != MAGIC_BYTE)
|
|
return PacketState.Unknown;
|
|
|
|
object type = ConvertByteToCommandType(Bytes[TypePosition]);
|
|
//CommandType type = (CommandType)Bytes[TypePosition];
|
|
byte command = Bytes[CommandPosition];
|
|
CommandStatus status = (CommandStatus)Bytes[StatusPosition];
|
|
byte deviceGroup = Bytes[DeviceGroupPosition];
|
|
byte deviceID = Bytes[DeviceIDPosition];
|
|
ushort parameterLength = (ushort)(Bytes[ParameterLengthPosition + 0] |
|
|
(Bytes[ParameterLengthPosition + 1] << 8));
|
|
|
|
// TODO: Why isn't this checking the CRCs?
|
|
|
|
//ushort headerCRC = (ushort)(Bytes[9] | (Bytes[8] << 8));
|
|
//ushort parameterCRC = (UInt16)(Bytes[10 + 1 + parameterLength] | Bytes[10 + 0 + parameterLength] << 8);
|
|
|
|
// Note that the second condition (parameterLength==0) is already caught above and does not need to
|
|
// be here.
|
|
if ((parameterLength > 0 && Bytes.Length < parameterLength + HEADER_SIZE_BYTES + DATA_CRC_SIZE_BYTES) ||
|
|
(0 == parameterLength && Bytes.Length < HEADER_SIZE_BYTES))
|
|
{
|
|
return PacketState.TooShort;
|
|
}
|
|
|
|
//if(Bytes.Length > parameterLength + 10 + 2)
|
|
// return PacketState.TooLong;
|
|
|
|
return PacketState.OK;
|
|
}
|
|
|
|
public override void ComputeCRCs()
|
|
{
|
|
HeaderCRC = 0xFFFF;
|
|
|
|
// Compute the CRC of the first 8 bytes in the CommandPacket
|
|
// This is a little more awkward than it should be but since the length field
|
|
// is really two bytes, but packed into the 16-bit variable, we need to mask it
|
|
// off and compute the CRC of the bytes in the correct order, etc.
|
|
//Utility.Utility.Crc16Ccitt crccalc = new Utility.Utility.Crc16Ccitt(Utility.Utility.InitialCrcValue.Zeros);
|
|
//crccalc.UpdateChecksum((ushort)0xFA);
|
|
//crccalc.UpdateChecksum((ushort)Type);
|
|
//crccalc.UpdateChecksum((ushort)Command);
|
|
//crccalc.UpdateChecksum((ushort)Status);
|
|
//crccalc.UpdateChecksum((ushort)DeviceGroup);
|
|
//crccalc.UpdateChecksum((ushort)DeviceID);
|
|
//crccalc.UpdateChecksum((ushort)(Parameter.Length & 0xFF));
|
|
//crccalc.UpdateChecksum((ushort)((Parameter.Length & 0xFF00) >> 8));
|
|
//HeaderCRC = crccalc.cur
|
|
|
|
HeaderCRC = Utils.Math_DoCRCCCITTStep(0xFA, HeaderCRC);
|
|
HeaderCRC = Utils.Math_DoCRCCCITTStep((ushort)((int)Type), HeaderCRC);
|
|
HeaderCRC = Utils.Math_DoCRCCCITTStep(GetCommand(), HeaderCRC);
|
|
HeaderCRC = Utils.Math_DoCRCCCITTStep((ushort)Status, HeaderCRC);
|
|
HeaderCRC = Utils.Math_DoCRCCCITTStep(DeviceGroup, HeaderCRC);
|
|
HeaderCRC = Utils.Math_DoCRCCCITTStep(DeviceID, HeaderCRC);
|
|
HeaderCRC = Utils.Math_DoCRCCCITTStep((ushort)(Parameter.Length & 0xFF), HeaderCRC);
|
|
HeaderCRC = Utils.Math_DoCRCCCITTStep((ushort)((Parameter.Length & 0xFF00) >> 8), HeaderCRC);
|
|
HeaderCRC = Utils.Math_DoCRCCCITTStep((ushort)(SequenceNumber & 0xFF), HeaderCRC);
|
|
HeaderCRC = Utils.Math_DoCRCCCITTStep((ushort)((SequenceNumber & 0xFF00) >> 8), HeaderCRC);
|
|
|
|
// Compute the Parameter CRC
|
|
ParameterCRC = 0xFFFF;
|
|
|
|
// If length > 0, continue the computation over the data bytes
|
|
if (Parameter.Length > 0)
|
|
{
|
|
for (int i = 0; i < Parameter.Length; i++)
|
|
{
|
|
ParameterCRC = Utils.Math_DoCRCCCITTStep(Parameter[i], ParameterCRC);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void GetParameter(int Offset, out double Value)
|
|
{
|
|
ByteConvertor.Convert(Parameter, Offset, out Value);
|
|
}
|
|
|
|
public void GetParameter(int Offset, out UInt64 Value)
|
|
{
|
|
Value = 0 |
|
|
(ulong)Parameter[Offset + 7] << 0 |
|
|
(ulong)Parameter[Offset + 6] << 8 |
|
|
(ulong)Parameter[Offset + 5] << 16 |
|
|
(ulong)Parameter[Offset + 4] << 24 |
|
|
(ulong)Parameter[Offset + 3] << 32 |
|
|
(ulong)Parameter[Offset + 2] << 40 |
|
|
(ulong)Parameter[Offset + 1] << 48 |
|
|
(ulong)Parameter[Offset + 0] << 56;
|
|
}
|
|
|
|
public void GetParameter(int Offset, out Int64 Value)
|
|
{
|
|
Value = (long)Parameter[Offset + 7] << 0 |
|
|
(long)Parameter[Offset + 6] << 8 |
|
|
(long)Parameter[Offset + 5] << 16 |
|
|
(long)Parameter[Offset + 4] << 24 |
|
|
(long)Parameter[Offset + 3] << 32 |
|
|
(long)Parameter[Offset + 2] << 40 |
|
|
(long)Parameter[Offset + 1] << 48 |
|
|
(long)Parameter[Offset + 0] << 56;
|
|
}
|
|
|
|
public void GetParameter(int Offset, out Int32 Value)
|
|
{
|
|
Value = Parameter[Offset + 3] |
|
|
Parameter[Offset + 2] << 8 |
|
|
Parameter[Offset + 1] << 16 |
|
|
Parameter[Offset + 0] << 24;
|
|
}
|
|
|
|
public void GetParameter(int Offset, out UInt32 Value)
|
|
{
|
|
Value = (UInt32)(Parameter[Offset + 3] |
|
|
Parameter[Offset + 2] << 8 |
|
|
Parameter[Offset + 1] << 16 |
|
|
Parameter[Offset + 0] << 24);
|
|
}
|
|
|
|
public void GetParameter(int Offset, out Int16 Value)
|
|
{
|
|
Value = (Int16)(Parameter[Offset + 1] |
|
|
Parameter[Offset + 0] << 8);
|
|
}
|
|
|
|
public void GetParameter(int Offset, out UInt16 Value)
|
|
{
|
|
Value = (UInt16)(Parameter[Offset + 1] |
|
|
Parameter[Offset + 0] << 8);
|
|
}
|
|
|
|
public void GetParameter(int Offset, out byte Value)
|
|
{
|
|
Value = Parameter[Offset];
|
|
}
|
|
|
|
public void GetParameter(int Offset, out bool Value)
|
|
{
|
|
Value = (Parameter[Offset] == 0x01);
|
|
}
|
|
|
|
public void GetParameter(int Offset, out float Value)
|
|
{
|
|
Value = BitConverter.ToSingle(Parameter, Offset);
|
|
}
|
|
|
|
public void GetParameter(int Offset, out string Value)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
int idx = Offset;
|
|
while (idx < Parameter.Length && 0 != Parameter[idx])
|
|
{
|
|
sb.Append((char)Parameter[idx++]);
|
|
}
|
|
Value = sb.ToString();
|
|
}
|
|
|
|
public void SetParameter(int Offset, double Value)
|
|
{
|
|
byte[] rv = ByteConvertor.ToByteArray(Value);
|
|
Buffer.BlockCopy(rv, 0, Parameter, Offset, rv.Length);
|
|
}
|
|
|
|
public void SetParameter(int Offset, Int64 Value)
|
|
{
|
|
Parameter[Offset + 7] = (byte)(((ulong)Value & 0x00000000000000FF) >> 0);
|
|
Parameter[Offset + 6] = (byte)(((ulong)Value & 0x000000000000FF00) >> 8);
|
|
Parameter[Offset + 5] = (byte)(((ulong)Value & 0x0000000000FF0000) >> 16);
|
|
Parameter[Offset + 4] = (byte)(((ulong)Value & 0x00000000FF000000) >> 24);
|
|
Parameter[Offset + 3] = (byte)(((ulong)Value & 0x000000FF00000000) >> 32);
|
|
Parameter[Offset + 2] = (byte)(((ulong)Value & 0x0000FF0000000000) >> 40);
|
|
Parameter[Offset + 1] = (byte)(((ulong)Value & 0x00FF000000000000) >> 48);
|
|
Parameter[Offset + 0] = (byte)(((ulong)Value & 0xFF00000000000000) >> 56);
|
|
}
|
|
|
|
public void SetParameter(int Offset, UInt64 Value)
|
|
{
|
|
Parameter[Offset + 7] = (byte)((Value & 0x00000000000000FF) >> 0);
|
|
Parameter[Offset + 6] = (byte)((Value & 0x000000000000FF00) >> 8);
|
|
Parameter[Offset + 5] = (byte)((Value & 0x0000000000FF0000) >> 16);
|
|
Parameter[Offset + 4] = (byte)((Value & 0x00000000FF000000) >> 24);
|
|
Parameter[Offset + 3] = (byte)((Value & 0x000000FF00000000) >> 32);
|
|
Parameter[Offset + 2] = (byte)((Value & 0x0000FF0000000000) >> 40);
|
|
Parameter[Offset + 1] = (byte)((Value & 0x00FF000000000000) >> 48);
|
|
Parameter[Offset + 0] = (byte)((Value & 0xFF00000000000000) >> 56);
|
|
}
|
|
|
|
public void SetParameter(int Offset, Int32 Value)
|
|
{
|
|
Parameter[Offset + 3] = (byte)((Value & 0x000000FF));
|
|
Parameter[Offset + 2] = (byte)((Value & 0x0000FF00) >> 8);
|
|
Parameter[Offset + 1] = (byte)((Value & 0x00FF0000) >> 16);
|
|
Parameter[Offset + 0] = (byte)((Value & 0xFF000000) >> 24);
|
|
}
|
|
|
|
public void SetParameter(int Offset, UInt32 Value)
|
|
{
|
|
Parameter[Offset + 3] = (byte)((Value & 0x000000FF));
|
|
Parameter[Offset + 2] = (byte)((Value & 0x0000FF00) >> 8);
|
|
Parameter[Offset + 1] = (byte)((Value & 0x00FF0000) >> 16);
|
|
Parameter[Offset + 0] = (byte)((Value & 0xFF000000) >> 24);
|
|
}
|
|
|
|
public void SetParameter(int Offset, Int16 Value)
|
|
{
|
|
Parameter[Offset + 1] = (byte)(Value & 0x00FF);
|
|
Parameter[Offset + 0] = (byte)((Value & 0xFF00) >> 8);
|
|
}
|
|
|
|
public void SetParameter(int Offset, UInt16 Value)
|
|
{
|
|
Parameter[Offset + 1] = (byte)(Value & 0x00FF);
|
|
Parameter[Offset + 0] = (byte)((Value & 0xFF00) >> 8);
|
|
}
|
|
|
|
public void SetParameter(int Offset, byte Value)
|
|
{
|
|
Parameter[Offset] = Value;
|
|
}
|
|
|
|
public void SetParameter(int Offset, bool Value)
|
|
{
|
|
Parameter[Offset] = (byte)(Value ? 0x01 : 0x00);
|
|
}
|
|
|
|
public void SetParameter(int Offset, byte[] Value)
|
|
{
|
|
Value.CopyTo(Parameter, Offset);
|
|
}
|
|
|
|
public void SetParameter(int Offset, string Value)
|
|
{
|
|
char[] original = Value.ToCharArray();
|
|
char[] withNullTermination = new char[original.Length + 1];
|
|
original.CopyTo(withNullTermination, 0);
|
|
withNullTermination[withNullTermination.Length - 1] = '\0';
|
|
SetParameter(Offset, withNullTermination);
|
|
}
|
|
|
|
public void SetParameter(int Offset, char[] Value)
|
|
{
|
|
for (int i = 0; i < Value.Length; i++)
|
|
{
|
|
Parameter[Offset + i] = (byte)Value[i];
|
|
}
|
|
Parameter[Parameter.Length - 1] = 0;
|
|
}
|
|
|
|
public void SetParameter(int Offset, char Value)
|
|
{
|
|
Parameter[Offset] = (byte)Value;
|
|
}
|
|
|
|
public void SetParameter(int Offset, float Value)
|
|
{
|
|
BitConverter.GetBytes(Value).CopyTo(Parameter, Offset);
|
|
}
|
|
|
|
public override byte[] ToBytes()
|
|
{
|
|
int Length;
|
|
byte[] CommandBytes;
|
|
|
|
Length = HEADER_SIZE_BYTES + Parameter.Length + (Parameter.Length > 0 ? DATA_CRC_SIZE_BYTES : 0);
|
|
CommandBytes = new byte[Length];
|
|
|
|
CommandBytes[MagicBytePosition] = MAGIC_BYTE;
|
|
CommandBytes[TypePosition] = (byte)((int)Type);
|
|
CommandBytes[CommandPosition] = GetCommand();
|
|
CommandBytes[StatusPosition] = (byte)Status;
|
|
CommandBytes[DeviceGroupPosition] = DeviceGroup;
|
|
CommandBytes[DeviceIDPosition] = DeviceID;
|
|
CommandBytes[ParameterLengthPosition + 0] = (byte)((Parameter.Length & 0xFF00) >> 8);
|
|
CommandBytes[ParameterLengthPosition + 1] = (byte)(Parameter.Length & 0x00FF);
|
|
CommandBytes[SequenceNumberPosition + 0] = (byte)((SequenceNumber & 0xFF00) >> 8);
|
|
CommandBytes[SequenceNumberPosition + 1] = (byte)(SequenceNumber & 0x00FF);
|
|
CommandBytes[HeaderCRCPosition + 0] = (byte)((HeaderCRC & 0xFF00) >> 8);
|
|
CommandBytes[HeaderCRCPosition + 1] = (byte)(HeaderCRC & 0x00FF);
|
|
|
|
for (int iIndex = 0; iIndex < Parameter.Length; iIndex++)
|
|
{
|
|
CommandBytes[iIndex + HEADER_SIZE_BYTES + DATA_CRC_SIZE_BYTES] = Parameter[iIndex];
|
|
}
|
|
|
|
if (Parameter.Length > 0)
|
|
{
|
|
CommandBytes[HEADER_SIZE_BYTES + 0] = (byte)((ParameterCRC & 0xFF00) >> 8);
|
|
CommandBytes[HEADER_SIZE_BYTES + 1] = (byte)(ParameterCRC & 0x00FF);
|
|
}
|
|
|
|
OriginalBytes = CommandBytes;
|
|
|
|
return CommandBytes;
|
|
}
|
|
}
|
|
}
|