You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 line
7.2 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using JTNE.Protocol.Enums;
  5. using JTNE.Protocol.Exceptions;
  6. using JTNE.Protocol.Extensions;
  7. using JTNE.Protocol.Internal;
  8. namespace JTNE.Protocol.Formatters {
  9. public class JTNEPackageFormatter : IJTNEFormatter<JTNEPackage> {
  10. private const byte FixedDataBodyLength = 2;
  11. public JTNEPackage Deserialize (ReadOnlySpan<byte> bytes, out int readSize) {
  12. int offset = 0;
  13. // 1.进行固定头校验
  14. if (bytes[offset] != JTNEPackage.BeginFlag && bytes[offset + 1] == JTNEPackage.BeginFlag)
  15. throw new JTNEException (JTNEErrorCode.BeginFlagError, $"{bytes[offset]},{bytes[offset + 1]}");
  16. // 2.进行BCC校验码
  17. // 校验位 = 报文长度 - 最后一位(校验位)
  18. if (!JTNEGlobalConfigs.Instance.SkipCRCCode) {
  19. byte bCCCode = bytes[bytes.Length - 1];
  20. byte bCCCode2 = bytes.ToXor (2, bytes.Length - 1);
  21. if (bCCCode != bCCCode2)
  22. throw new JTNEException (JTNEErrorCode.BCCCodeError, $"request:{bCCCode}!=calculate:{bCCCode2}");
  23. }
  24. JTNEPackage jTNEPackage = new JTNEPackage ();
  25. offset += 2;
  26. // 3.命令标识
  27. jTNEPackage.MsgId = (JTNEMsgId)JTNEBinaryExtensions.ReadByteLittle (bytes, ref offset);
  28. // 4.应答标识
  29. jTNEPackage.AskId = (JTNEAskId)JTNEBinaryExtensions.ReadByteLittle (bytes, ref offset);
  30. // 5.VIN
  31. jTNEPackage.VIN = JTNEBinaryExtensions.ReadStringLittle (bytes, ref offset, 17);
  32. // 6.数据加密方式
  33. jTNEPackage.EncryptMethod = (JTNEEncryptMethod) JTNEBinaryExtensions.ReadByteLittle (bytes, ref offset);
  34. // 7.数据单元长度是数据单元的总字节数
  35. jTNEPackage.DataUnitLength = JTNEBinaryExtensions.ReadUInt16Little (bytes, ref offset);
  36. // 8.数据体
  37. // 8.1.根据数据加密方式进行解码
  38. // 8.2.解析出对应数据体
  39. if (jTNEPackage.DataUnitLength > 0) {
  40. Type jTNEBodiesImplType = JTNEMsgIdFactory.GetBodyTypeByMsgId ((byte)jTNEPackage.MsgId);
  41. if (jTNEBodiesImplType != null) {
  42. int bodyReadSize = 0;
  43. try {
  44. if (jTNEPackage.EncryptMethod == JTNEEncryptMethod.None) {
  45. jTNEPackage.Bodies = JTNEFormatterResolverExtensions.JTNEDynamicDeserialize (
  46. JTNEFormatterExtensions.GetFormatter (jTNEBodiesImplType),
  47. bytes.Slice (offset, jTNEPackage.DataUnitLength),
  48. out bodyReadSize);
  49. } else {
  50. if (JTNEGlobalConfigs.Instance.DataBodiesEncrypt != null) {
  51. var data = JTNEGlobalConfigs.Instance.DataBodiesEncrypt (jTNEPackage.EncryptMethod)
  52. .Decrypt (bytes.Slice (offset, jTNEPackage.DataUnitLength).ToArray ());
  53. jTNEPackage.Bodies = JTNEFormatterResolverExtensions.JTNEDynamicDeserialize (
  54. JTNEFormatterExtensions.GetFormatter (jTNEBodiesImplType),
  55. data,
  56. out bodyReadSize);
  57. }
  58. }
  59. } catch (Exception ex) {
  60. throw new JTNEException (JTNEErrorCode.BodiesParseError, ex);
  61. }
  62. offset += bodyReadSize;
  63. }
  64. }
  65. // 9.校验码
  66. jTNEPackage.BCCCode = JTNEBinaryExtensions.ReadByteLittle (bytes, ref offset);
  67. readSize = offset;
  68. return jTNEPackage;
  69. }
  70. public int Serialize (ref byte[] bytes, int offset, JTNEPackage value) {
  71. // 1.起始符1
  72. offset += JTNEBinaryExtensions.WriteByteLittle (bytes, offset, value.BeginFlag1);
  73. // 2.起始符2
  74. offset += JTNEBinaryExtensions.WriteByteLittle (bytes, offset, value.BeginFlag2);
  75. // 3.命令标识
  76. offset += JTNEBinaryExtensions.WriteByteLittle (bytes, offset, (byte)value.MsgId);
  77. // 4.应答标识
  78. offset += JTNEBinaryExtensions.WriteByteLittle (bytes, offset, (byte)value.AskId);
  79. // 5.VIN
  80. offset += JTNEBinaryExtensions.WriteStringPadRightLittle (bytes, offset, value.VIN, 17);
  81. // 6.数据加密方式
  82. offset += JTNEBinaryExtensions.WriteByteLittle (bytes, offset, (byte) value.EncryptMethod);
  83. // 7.记录当前偏移量
  84. int tmpOffset = offset;
  85. // 8.数据体
  86. Type jTNEBodiesImplType = JTNEMsgIdFactory.GetBodyTypeByMsgId ((byte)value.MsgId);
  87. int messageBodyOffset = 0;
  88. if (jTNEBodiesImplType != null) {
  89. if (value.Bodies != null) {
  90. // 8.1.处理数据体
  91. // 8.2.判断是否有加密
  92. messageBodyOffset = JTNEFormatterResolverExtensions.JTNEDynamicSerialize (
  93. JTNEFormatterExtensions.GetFormatter (jTNEBodiesImplType),
  94. ref bytes,
  95. offset + FixedDataBodyLength,
  96. value.Bodies);
  97. if (value.EncryptMethod == JTNEEncryptMethod.None) {
  98. // 9.通过tmpOffset反写数据单元长度
  99. JTNEBinaryExtensions.WriteUInt16Little (bytes, tmpOffset, (ushort) (messageBodyOffset - offset - FixedDataBodyLength));
  100. offset = messageBodyOffset;
  101. } else {
  102. if (JTNEGlobalConfigs.Instance.DataBodiesEncrypt != null) {
  103. // 8.1.先进行分割数据体
  104. var bodiesData = bytes.AsSpan (tmpOffset + FixedDataBodyLength, messageBodyOffset - offset - FixedDataBodyLength).ToArray ();
  105. // 8.2.将数据体进行加密
  106. var data = JTNEGlobalConfigs.Instance.DataBodiesEncrypt (value.EncryptMethod)
  107. .Encrypt (bodiesData);
  108. // 9.通过tmpOffset反写加密后数据单元长度
  109. JTNEBinaryExtensions.WriteUInt16Little (bytes, tmpOffset, (ushort) data.Length);
  110. // 8.3.写入加密后的数据体
  111. offset += FixedDataBodyLength;
  112. offset += JTNEBinaryExtensions.WriteBytesLittle (bytes, offset, data);
  113. }
  114. }
  115. } else {
  116. // 9.数据单元长度
  117. offset += JTNEBinaryExtensions.WriteUInt16Little (bytes, offset, 0);
  118. }
  119. } else {
  120. // 9.数据单元长度
  121. offset += JTNEBinaryExtensions.WriteUInt16Little (bytes, offset, 0);
  122. }
  123. // 10.校验码
  124. var bccCode = bytes.ToXor (2, offset);
  125. offset += JTNEBinaryExtensions.WriteByteLittle (bytes, offset, bccCode);
  126. return offset;
  127. }
  128. }
  129. }