您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

243 行
9.4 KiB

  1. using JT808.Protocol.Attributes;
  2. using JT808.Protocol.Enums;
  3. using JT808.Protocol.Exceptions;
  4. using JT808.Protocol.Extensions;
  5. using JT808.Protocol.Formatters;
  6. using JT808.Protocol.MessagePack;
  7. using System;
  8. namespace JT808.Protocol
  9. {
  10. /// <summary>
  11. /// JT808数据包
  12. /// </summary>
  13. public class JT808Package:IJT808MessagePackFormatter<JT808Package>
  14. {
  15. /// <summary>
  16. /// 起始符
  17. /// </summary>
  18. public const byte BeginFlag = 0x7e;
  19. /// <summary>
  20. /// 终止符
  21. /// </summary>
  22. public const byte EndFlag = 0x7e;
  23. /// <summary>
  24. /// 起始符
  25. /// </summary>
  26. public byte Begin { get; set; } = BeginFlag;
  27. /// <summary>
  28. /// 头数据
  29. /// </summary>
  30. public JT808Header Header { get; set; }
  31. /// <summary>
  32. /// 数据体
  33. /// </summary>
  34. public JT808Bodies Bodies { get; set; }
  35. /// <summary>
  36. /// 校验码
  37. /// 从消息头开始,同后一字节异或,直到校验码前一个字节,占用一个字节。
  38. /// </summary>
  39. public byte CheckCode { get; set; }
  40. /// <summary>
  41. /// 终止符
  42. /// </summary>
  43. public byte End { get; set; } = EndFlag;
  44. /// <summary>
  45. /// 808版本号
  46. /// </summary>
  47. public JT808Version Version
  48. {
  49. get
  50. {
  51. if (Header != null)
  52. {
  53. try
  54. {
  55. if (Header.MessageBodyProperty.VersionFlag)
  56. {
  57. return JT808Version.JTT2019;
  58. }
  59. else
  60. {
  61. return JT808Version.JTT2013;
  62. }
  63. }
  64. catch
  65. {
  66. return JT808Version.JTT2013;
  67. }
  68. }
  69. else
  70. {
  71. return JT808Version.JTT2013;
  72. }
  73. }
  74. }
  75. public JT808Package Deserialize(ref JT808MessagePackReader reader, IJT808Config config)
  76. {
  77. // 1. 验证校验和
  78. if (!config.SkipCRCCode)
  79. {
  80. if (!reader.CheckXorCodeVali)
  81. {
  82. throw new JT808Exception(JT808ErrorCode.CheckCodeNotEqual, $"{reader.RealCheckXorCode}!={reader.CalculateCheckXorCode}");
  83. }
  84. }
  85. JT808Package jT808Package = new JT808Package();
  86. // ---------------开始解包--------------
  87. // 2.读取起始位置
  88. jT808Package.Begin = reader.ReadStart();
  89. // 3.读取头部信息
  90. jT808Package.Header = new JT808Header();
  91. // 3.1.读取消息Id
  92. jT808Package.Header.MsgId = reader.ReadUInt16();
  93. // 3.2.读取消息体属性
  94. jT808Package.Header.MessageBodyProperty = new JT808HeaderMessageBodyProperty(reader.ReadUInt16());
  95. if (jT808Package.Header.MessageBodyProperty.VersionFlag)
  96. {
  97. //2019版本
  98. jT808Package.Header.ProtocolVersion = reader.ReadByte();
  99. // 3.4.读取终端手机号
  100. jT808Package.Header.TerminalPhoneNo = reader.ReadBCD(20, config.Trim);
  101. reader.Version = JT808Version.JTT2019;
  102. }
  103. else
  104. {
  105. //2013版本
  106. // 3.3.读取终端手机号
  107. jT808Package.Header.TerminalPhoneNo = reader.ReadBCD(config.TerminalPhoneNoLength, config.Trim);
  108. }
  109. // 3.4.读取消息流水号
  110. jT808Package.Header.MsgNum = reader.ReadUInt16();
  111. // 3.5.判断有无分包
  112. if (jT808Package.Header.MessageBodyProperty.IsPackage)
  113. {
  114. //3.5.1.读取消息包总数
  115. jT808Package.Header.PackgeCount = reader.ReadUInt16();
  116. //3.5.2.读取消息包序号
  117. jT808Package.Header.PackageIndex = reader.ReadUInt16();
  118. }
  119. // 4.处理数据体
  120. // 4.1.判断有无数据体
  121. if (jT808Package.Header.MessageBodyProperty.DataLength > 0)
  122. {
  123. if(config.MsgIdFactory.TryGetValue(jT808Package.Header.MsgId,out object instance))
  124. {
  125. if (jT808Package.Header.MessageBodyProperty.IsPackage)
  126. {
  127. if (jT808Package.Header.PackageIndex > 1)
  128. {
  129. try
  130. {
  131. //4.2处理第二包之后的分包数据消息体
  132. JT808SplitPackageBodies jT808SplitPackageBodies = new JT808SplitPackageBodies();
  133. jT808Package.Bodies = jT808SplitPackageBodies.Deserialize(ref reader, config);
  134. }
  135. catch (Exception ex)
  136. {
  137. throw new JT808Exception(JT808ErrorCode.BodiesParseError, ex);
  138. }
  139. }
  140. else
  141. {
  142. try
  143. {
  144. //4.2.处理消息体
  145. jT808Package.Bodies = JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(
  146. instance,
  147. ref reader, config);
  148. }
  149. catch (Exception ex)
  150. {
  151. throw new JT808Exception(JT808ErrorCode.BodiesParseError, ex);
  152. }
  153. }
  154. }
  155. else
  156. {
  157. try
  158. {
  159. //4.2.处理消息体
  160. jT808Package.Bodies = JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(
  161. instance,
  162. ref reader, config);
  163. }
  164. catch (Exception ex)
  165. {
  166. throw new JT808Exception(JT808ErrorCode.BodiesParseError, ex);
  167. }
  168. }
  169. }
  170. }
  171. // 5.读取校验码
  172. jT808Package.CheckCode = reader.ReadByte();
  173. // 6.读取终止位置
  174. jT808Package.End = reader.ReadEnd();
  175. // ---------------解包完成--------------
  176. return jT808Package;
  177. }
  178. public void Serialize(ref JT808MessagePackWriter writer, JT808Package value, IJT808Config config)
  179. {
  180. // ---------------开始组包--------------
  181. // 1.起始符
  182. writer.WriteStart();
  183. // 2.写入头部 //部分有带数据体的长度,那么先跳过写入头部部分
  184. // 2.1.消息ID
  185. writer.WriteUInt16(value.Header.MsgId);
  186. // 2.2.消息体属性(包含消息体长度所以先跳过)
  187. writer.Skip(2, out int msgBodiesPropertyPosition);
  188. if (value.Header.MessageBodyProperty.VersionFlag)
  189. {
  190. //2019版本
  191. // 2.3.协议版本号
  192. writer.WriteByte(value.Header.ProtocolVersion);
  193. // 2.4.终端手机号
  194. writer.WriteBCD(value.Header.TerminalPhoneNo, 20);
  195. writer.Version = JT808Version.JTT2019;
  196. }
  197. else
  198. {
  199. //2013版本
  200. // 2.3.终端手机号 (写死大陆手机号码)
  201. writer.WriteBCD(value.Header.TerminalPhoneNo, config.TerminalPhoneNoLength);
  202. }
  203. value.Header.MsgNum = value.Header.MsgNum > 0 ? value.Header.MsgNum : config.MsgSNDistributed.Increment();
  204. // 2.4.消息流水号
  205. writer.WriteUInt16(value.Header.MsgNum);
  206. // 2.5.判断是否分包
  207. if (value.Header.MessageBodyProperty.IsPackage)
  208. {
  209. // 2.5.1.消息包总数
  210. writer.WriteUInt16(value.Header.PackgeCount);
  211. // 2.5.2.消息包序号
  212. writer.WriteUInt16(value.Header.PackageIndex);
  213. }
  214. int headerLength = writer.GetCurrentPosition();
  215. // 3.处理数据体部分
  216. if (value.Bodies != null)
  217. {
  218. if (!value.Bodies.SkipSerialization)
  219. {
  220. JT808MessagePackFormatterResolverExtensions.JT808DynamicSerialize(value.Bodies,
  221. ref writer, value.Bodies,
  222. config);
  223. }
  224. }
  225. // 3.1.处理数据体长度
  226. // 2.2.回写消息体属性
  227. value.Header.MessageBodyProperty.DataLength = (writer.GetCurrentPosition() - headerLength);
  228. writer.WriteUInt16Return(value.Header.MessageBodyProperty.Wrap(), msgBodiesPropertyPosition);
  229. // 4.校验码
  230. writer.WriteXor();
  231. // 5.终止符
  232. writer.WriteEnd();
  233. // 6.编码
  234. writer.WriteEncode();
  235. // ---------------组包结束--------------
  236. }
  237. }
  238. }