Files
DP44/DataPRO/ICommand/SliceCommandPacketBase.cs
2026-04-17 14:55:32 -04:00

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;
}
}
}