using GBNewEnergy.Protocol.Enums; using GBNewEnergy.Protocol.Exceptions; using GBNewEnergy.Protocol.Extensions; using GBNewEnergy.Protocol.NEProperties; using System; using System.IO; namespace GBNewEnergy.Protocol { /// /// 新能源包 /// public class NEPackage : NEBufferedEntityBase { public NEPackage(byte[] header, byte[] body, NEGlobalConfigs nEConfigs) : base(header, body, nEConfigs) { } public NEPackage(byte[] buf, NEGlobalConfigs nEConfigs) : base(buf, nEConfigs) { } public NEPackage(INEProperties nEProperties, NEGlobalConfigs nEConfigs) : base(nEProperties, nEConfigs) { } /// /// 固定为24个字节长度 /// public const int HeaderFixedByteLength = 24; /// /// 起始符 /// public const byte BeginFlag = 0x23; /// /// 校验位1字节 /// private const int CheckBit = 1; /// /// 命令标识 /// public NEMsgId MsgId { get; private set; } /// /// 应答标志 /// public NEAskId AskId { get; private set; } /// /// 车辆识别码 /// public string VIN { get; private set; } /// /// 数据加密方式 /// 0x01:数据不加密;0x02:数据经过 RSA 算法加密;0x03:数据经过 AES128 位算法加密;“0xFE”表示异常,“0xFF”表示无效 /// public NEEncryptMethod EncryptMethod { get; private set; } /// /// 数据单元长度是数据单元的总字节数,有效值范围:0-65531 /// public int DataUnitLength { get; private set; } /// /// 采用BCC(异或检验)法,校验范围从命令单元的第一个字节开始,同后一个字节异或,直到校验码前一个字节为止, /// 校验码占用一个字节,当数据单元存在加密时,应先加密后检验,先校验后解密 /// public byte BCCCode { get; private set; } /// /// 头数据 /// public byte[] Header { get; private set; } /// /// 数据体 /// public NEBodies Bodies { get; protected set; } protected override void ToBuffer() { // 固定单元长度 DataUnitLength = Bodies.Buffer.Length; Buffer = new byte[HeaderFixedByteLength + DataUnitLength + CheckBit]; Buffer[0] = BeginFlag; Buffer[1] = BeginFlag; Buffer[2] = (byte)MsgId; Buffer[3] = (byte)AskId; Buffer.WriteLittle(VIN, 4); Buffer[21] = (byte)EncryptMethod; Buffer.WriteLittle(DataUnitLength, 22, 2); if (NEConfigs.Encrypt != null) { Buffer.WriteLittle(NEConfigs.Encrypt.Encrypt(Bodies.Buffer), 24, DataUnitLength); } else { Buffer.WriteLittle(Bodies.Buffer, 24, DataUnitLength); } BCCCode = Buffer.ToXor(2, (HeaderFixedByteLength + DataUnitLength - 1)); Buffer[HeaderFixedByteLength + DataUnitLength] = BCCCode; Header = new byte[HeaderFixedByteLength]; Array.Copy(Buffer, 0, Header, 0, HeaderFixedByteLength); } protected override void InitializeProperties(INEProperties nEProperties) { NEPackageProperty nEPackageProperty = (NEPackageProperty)nEProperties; VIN = nEPackageProperty.VIN; MsgId = nEPackageProperty.MsgId; AskId = nEPackageProperty.AskId; Bodies = nEPackageProperty.Bodies; EncryptMethod = NEConfigs.EncryptMethod; } protected override void InitializePropertiesFromBuffer() { if (Buffer[0] != BeginFlag && Buffer[1] == BeginFlag) throw new NEException(NEErrorCode.BeginFlagError, $"{Buffer[0]},{Buffer[1]}"); MsgId = (NEMsgId)Buffer[2]; AskId = (NEAskId)Buffer[3]; VIN = Buffer.ReadStringLittle(4, 17); EncryptMethod = (NEEncryptMethod)Buffer[21]; DataUnitLength = Buffer.ReadUShortH2LLittle(22, 2); // 进行BCC校验码 // 校验位 = 报文长度 - 最后一位(校验位) - 偏移量(2) int checkBit = Buffer.Length - CheckBit - 2; byte bCCCode = Buffer.ToXor(2, checkBit); byte bCCCode2 = Buffer[Buffer.Length - CheckBit]; if (bCCCode != bCCCode2) { throw new NEException(NEErrorCode.BCCCodeError, $"request:{bCCCode2}!=calculate:{bCCCode}"); } BCCCode = bCCCode2; byte[] bodiesBytes = new byte[DataUnitLength + CheckBit]; Array.Copy(Buffer, HeaderFixedByteLength, bodiesBytes, 0, bodiesBytes.Length); if (NEConfigs.Encrypt != null) { Bodies = NEBodiesFactory.GetNEBodiesByMsgId(MsgId, NEConfigs.Encrypt.Decrypt(bodiesBytes),NEConfigs); } else { Bodies = NEBodiesFactory.GetNEBodiesByMsgId(MsgId, bodiesBytes, NEConfigs); } Header = new byte[HeaderFixedByteLength]; Array.Copy(Buffer, 0, Header, 0, HeaderFixedByteLength); } } }