25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

270 lines
13 KiB

  1. using JT809.Protocol.Enums;
  2. using JT809.Protocol.Exceptions;
  3. using JT809.Protocol.Extensions;
  4. using JT809.Protocol.Formatters;
  5. using JT809.Protocol.Interfaces;
  6. using JT809.Protocol.MessagePack;
  7. using System;
  8. using System.Text.Json;
  9. namespace JT809.Protocol
  10. {
  11. public class JT809Package:IJT809MessagePackFormatter<JT809Package>, IJT809Analyze, IJT809_2019_Version
  12. {
  13. public const byte BEGINFLAG = 0X5B;
  14. public const byte ENDFLAG = 0X5D;
  15. /// <summary>
  16. /// 固定为26个字节长度
  17. /// <para>Head flag + Message Header + CRC Code + End Flag</para>
  18. /// <para>1 + 22 + 2 + 1 = 26</para>
  19. /// </summary>
  20. public const int FixedByteLength = 26;
  21. /// <summary>
  22. /// 固定为26个字节长度
  23. /// <para>Head flag + Message Header + CRC Code + End Flag</para>
  24. /// <para>1 + 30 + 2 + 1 = 26</para>
  25. /// </summary>
  26. public const int FixedByteLength_2019 = 34;
  27. public byte BeginFlag { get; set; } = BEGINFLAG;
  28. public JT809Header Header { get; set; }
  29. public JT809Bodies Bodies { get; set; }
  30. public ushort CRCCode { get; set; }
  31. public byte EndFlag { get; set; } = ENDFLAG;
  32. public JT809Package Deserialize(ref JT809MessagePackReader reader, IJT809Config config)
  33. {
  34. // 1. 验证校验码
  35. if (!config.SkipCRCCode)
  36. {
  37. // 1.2. 验证校验码
  38. if (!reader.CheckXorCodeVali)
  39. {
  40. throw new JT809Exception(JT809ErrorCode.CRC16CheckInvalid, $"{reader.CalculateCheckXorCode}!={reader.RealCheckXorCode}");
  41. }
  42. }
  43. JT809Package jT809Package = new JT809Package();
  44. // 2.读取起始头
  45. jT809Package.BeginFlag = reader.ReadStart();
  46. // 3.初始化消息头
  47. try
  48. {
  49. jT809Package.Header = config.GetMessagePackFormatter<JT809Header>().Deserialize(ref reader, config);
  50. }
  51. catch (Exception ex)
  52. {
  53. throw new JT809Exception(JT809ErrorCode.HeaderParseError, $"offset>{reader.ReadCurrentRemainContentLength()}", ex);
  54. }
  55. // 5.数据体处理
  56. // 5.1 判断是否有数据体(总长度-固定长度)> 0
  57. int fixedByteLength = config.Version == JT809Version.JTT2019 ? FixedByteLength_2019 : FixedByteLength;
  58. if ((jT809Package.Header.MsgLength - fixedByteLength) > 0)
  59. {
  60. if (config.BusinessTypeFactory.TryGetValue(jT809Package.Header.BusinessType, config.Version, out object instance))
  61. {
  62. try
  63. {
  64. // 5.2 是否加密
  65. switch (jT809Package.Header.EncryptFlag)
  66. {
  67. case JT809Header_Encrypt.None:
  68. // 5.3 处理消息体
  69. jT809Package.Bodies = JT809MessagePackFormatterResolverExtensions.JT809DynamicDeserialize(instance,ref reader, config);
  70. break;
  71. case JT809Header_Encrypt.Common:
  72. // 5.4. 处理加密消息体
  73. byte[] bodiesData = config.Encrypt.Decrypt(reader.ReadContent(), config.EncryptOptions, jT809Package.Header.EncryptKey);
  74. JT809MessagePackReader bodiesReader = new JT809MessagePackReader(bodiesData);
  75. jT809Package.Bodies = JT809MessagePackFormatterResolverExtensions.JT809DynamicDeserialize(instance,ref bodiesReader, config);
  76. break;
  77. }
  78. }
  79. catch (Exception ex)
  80. {
  81. throw new JT809Exception(JT809ErrorCode.BodiesParseError, $"offset>{reader.ReadCurrentRemainContentLength().ToString()}", ex);
  82. }
  83. }
  84. }
  85. jT809Package.CRCCode = reader.ReadUInt16();
  86. jT809Package.EndFlag = reader.ReadEnd();
  87. return jT809Package;
  88. }
  89. public void Serialize(ref JT809MessagePackWriter writer, JT809Package value, IJT809Config config)
  90. {
  91. // -----------开始组包----------
  92. // 1.起始符
  93. writer.WriteByte(value.BeginFlag);
  94. // 2.写入头部数据
  95. // 2.1.跳过数据长度的写入
  96. writer.Skip(4, out int lengthPosition);
  97. // 2.2.报文序列号
  98. value.Header.MsgSN = value.Header.MsgSN > 0 ? value.Header.MsgSN : config.MsgSNDistributed.Increment();
  99. writer.WriteUInt32(value.Header.MsgSN);
  100. // 2.3.业务数据类型
  101. writer.WriteUInt16(value.Header.BusinessType);
  102. // 2.4.下级平台接入码
  103. writer.WriteUInt32(value.Header.MsgGNSSCENTERID);
  104. // 2.5.版本号
  105. writer.WriteArray(value.Header.Version.Buffer);
  106. // 2.6.报文加密
  107. writer.WriteByte((byte)value.Header.EncryptFlag);
  108. // 2.7.数据加密密钥
  109. writer.WriteUInt32(value.Header.EncryptKey);
  110. if(config.Version== JT809Version.JTT2019)
  111. {
  112. // 2.8.UTC时间戳
  113. writer.WriteUTCDateTime(value.Header.Time);
  114. }
  115. // 3.写入数据体
  116. // 3.1.记录当前开始位置
  117. int startIndex = writer.GetCurrentPosition();
  118. // 3.2.写入数据对应数据体
  119. if (value.Bodies != null)
  120. {
  121. JT809MessagePackFormatterResolverExtensions.JT809DynamicSerialize(value.Bodies,ref writer, value.Bodies,config);
  122. }
  123. // 3.3.记录当前结束位置
  124. int endIndex = writer.GetCurrentPosition();
  125. int contentLength = endIndex - startIndex;
  126. if (contentLength > 0)
  127. {
  128. // 3.4. 数据加密
  129. switch (value.Header.EncryptFlag)
  130. {
  131. case JT809Header_Encrypt.None:
  132. break;
  133. case JT809Header_Encrypt.Common:
  134. // 3.5. 提取数据体并进行加密处理
  135. byte[] messageBodyDatEncrypted = config.Encrypt.Encrypt(writer.Extract(startIndex), config.EncryptOptions, value.Header.EncryptKey);
  136. int flagLength = messageBodyDatEncrypted.Length - contentLength;
  137. if (flagLength == 0)
  138. {
  139. // 相等复制
  140. writer.CopyTo(messageBodyDatEncrypted, startIndex);
  141. }
  142. else if (flagLength > 0)
  143. {
  144. // 扩容
  145. writer.Skip(flagLength, out _);
  146. writer.CopyTo(messageBodyDatEncrypted, startIndex);
  147. }
  148. else
  149. {
  150. // 缩减
  151. writer.CopyTo(messageBodyDatEncrypted, startIndex);
  152. writer.Shrink(-flagLength);
  153. }
  154. break;
  155. }
  156. }
  157. // 4.计算内容的总长度(校验码2+终止符1=3)
  158. writer.WriteInt32Return(writer.GetCurrentPosition() + 3, lengthPosition);
  159. // 5.校验码
  160. writer.WriteCRC16();
  161. // 6.终止符
  162. writer.WriteByte(value.EndFlag);
  163. // 7.转义
  164. writer.WriteEncode();
  165. // -----------组包完成----------
  166. }
  167. public void Analyze(ref JT809MessagePackReader reader, Utf8JsonWriter writer, IJT809Config config)
  168. {
  169. JT809Package jT809Package = new JT809Package();
  170. writer.WriteStartObject();
  171. // 2.读取起始头
  172. jT809Package.BeginFlag = reader.ReadStart();
  173. writer.WriteNumber($"[{jT809Package.BeginFlag.ReadNumber()}]起始标识", jT809Package.BeginFlag);
  174. // 3.初始化消息头
  175. JT809Header jT809Header=new JT809Header();
  176. writer.WriteStartObject("消息头");
  177. try
  178. {
  179. jT809Header.MsgLength = reader.ReadUInt32();
  180. writer.WriteNumber($"[{jT809Header.MsgLength.ReadNumber()}]数据长度", jT809Header.MsgLength);
  181. jT809Header.MsgSN = reader.ReadUInt32();
  182. writer.WriteNumber($"[{jT809Header.MsgSN.ReadNumber()}]报文序列号", jT809Header.MsgSN);
  183. jT809Header.BusinessType = reader.ReadUInt16();
  184. writer.WriteString($"[{jT809Header.BusinessType.ReadNumber()}]业务类型标识", ((JT809BusinessType)jT809Header.BusinessType).ToString());
  185. jT809Header.MsgGNSSCENTERID = reader.ReadUInt32();
  186. writer.WriteNumber($"[{jT809Header.MsgGNSSCENTERID.ReadNumber()}]下级平台接入码", jT809Header.MsgGNSSCENTERID);
  187. var virtualHex = reader.ReadVirtualArray(JT809Header_Version.FixedByteLength);
  188. jT809Header.Version = new JT809Header_Version(reader.ReadArray(JT809Header_Version.FixedByteLength));
  189. writer.WriteString($"[{virtualHex.ToArray().ToHexString()}]协议版本号标识", jT809Header.Version.ToString());
  190. jT809Header.EncryptFlag = (JT809Header_Encrypt)reader.ReadByte();
  191. writer.WriteString($"[{ jT809Header.EncryptFlag.ToByteValue()}]报文加密标识位", jT809Header.EncryptFlag.ToString());
  192. jT809Header.EncryptKey = reader.ReadUInt32();
  193. writer.WriteNumber($"[{jT809Header.EncryptKey.ReadNumber()}]数据加密的密匙", jT809Header.EncryptKey);
  194. if (config.Version == JT809Version.JTT2019)
  195. {
  196. virtualHex = reader.ReadVirtualArray(8);
  197. jT809Header.Time = reader.ReadUTCDateTime();
  198. writer.WriteString($"[{virtualHex.ToArray().ToHexString()}]发送消息时的系统UTC时间", jT809Header.Time);
  199. }
  200. }
  201. catch (Exception ex)
  202. {
  203. writer.WriteString($"[{(int)JT809ErrorCode.HeaderParseError}]消息头异常", $"offset>{reader.ReadCurrentRemainContentLength()},异常消息:{ex.Message}");
  204. }
  205. writer.WriteEndObject();
  206. writer.WriteStartObject("消息体");
  207. // 5.数据体处理
  208. // 5.1 判断是否有数据体(总长度-固定长度)> 0
  209. int fixedByteLength = config.Version == JT809Version.JTT2019 ? FixedByteLength_2019 : FixedByteLength;
  210. if ((jT809Header.MsgLength - fixedByteLength) > 0)
  211. {
  212. if (config.BusinessTypeFactory.TryGetValue(jT809Header.BusinessType, config.Version, out object instance))
  213. {
  214. try
  215. {
  216. // 5.2 是否加密
  217. switch (jT809Header.EncryptFlag)
  218. {
  219. case JT809Header_Encrypt.None:
  220. // 5.3 处理消息体
  221. instance.Analyze(ref reader, writer, config);
  222. break;
  223. case JT809Header_Encrypt.Common:
  224. // 5.4. 处理加密消息体
  225. byte[] bodiesData = config.Encrypt.Decrypt(reader.ReadContent(), config.EncryptOptions, jT809Header.EncryptKey);
  226. JT809MessagePackReader bodiesReader = new JT809MessagePackReader(bodiesData);
  227. instance.Analyze(ref bodiesReader, writer, config);
  228. break;
  229. }
  230. }
  231. catch (Exception ex)
  232. {
  233. writer.WriteString($"[{(int)JT809ErrorCode.BodiesParseError}]消息体异常", $"offset>{reader.ReadCurrentRemainContentLength()},异常消息:{ex.Message}");
  234. }
  235. }
  236. }
  237. writer.WriteEndObject();
  238. jT809Package.CRCCode = reader.ReadUInt16();
  239. writer.WriteNumber($"[{jT809Package.CRCCode.ReadNumber()}]校验码", jT809Package.CRCCode);
  240. // 1. 验证校验码
  241. if (!config.SkipCRCCode)
  242. {
  243. // 1.2. 验证校验码
  244. if (!reader.CheckXorCodeVali)
  245. {
  246. writer.WriteString($"[{(int)JT809ErrorCode.CRC16CheckInvalid}]校验码异常", $"{reader.CalculateCheckXorCode}!={reader.RealCheckXorCode}");
  247. }
  248. }
  249. jT809Package.EndFlag = reader.ReadEnd();
  250. writer.WriteNumber($"[{jT809Package.EndFlag.ReadNumber()}]结束标识", jT809Package.EndFlag);
  251. writer.WriteEndObject();
  252. }
  253. }
  254. }