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.

425 lines
15 KiB

  1. using JT809.Protocol.Buffers;
  2. using JT809.Protocol.Extensions;
  3. using System;
  4. using System.Buffers;
  5. using System.Buffers.Binary;
  6. using System.Collections.Generic;
  7. using System.Runtime.CompilerServices;
  8. using System.Text;
  9. namespace JT809.Protocol.MessagePack
  10. {
  11. public ref struct JT809MessagePackReader
  12. {
  13. public ReadOnlySpan<byte> Reader { get; private set; }
  14. public ReadOnlySpan<byte> SrcBuffer { get; }
  15. public int ReaderCount { get; private set; }
  16. private ushort _calculateCheckCRCCode;
  17. private ushort _realCheckCRCCode;
  18. private bool _checkCRCCodeVali;
  19. /// <summary>
  20. /// 是否进行解码操作
  21. /// 若进行解码操作,则对应的是一个正常的包
  22. /// 若不进行解码操作,则对应的是一个非正常的包(头部包,数据体包等等)
  23. /// 主要用来一次性读取所有数据体内容操作
  24. /// </summary>
  25. private bool _decoded;
  26. private static byte[] decode5a01 = new byte[] { 0x5a, 0x01 };
  27. private static byte[] decode5a02 = new byte[] { 0x5a, 0x02 };
  28. private static byte[] decode5e01 = new byte[] { 0x5e, 0x01 };
  29. private static byte[] decode5e02 = new byte[] { 0x5e, 0x02 };
  30. /// <summary>
  31. /// 解码(转义还原),计算校验和
  32. /// </summary>
  33. /// <param name="buffer"></param>
  34. public JT809MessagePackReader(ReadOnlySpan<byte> srcBuffer)
  35. {
  36. SrcBuffer = srcBuffer;
  37. ReaderCount = 0;
  38. _realCheckCRCCode = 0x00;
  39. _calculateCheckCRCCode = 0xFFFF;
  40. _checkCRCCodeVali = false;
  41. _decoded = false;
  42. Reader = srcBuffer;
  43. }
  44. /// <summary>
  45. /// 在解码的时候把校验和也计算出来,避免在循环一次进行校验
  46. /// </summary>
  47. /// <returns></returns>
  48. public void Decode()
  49. {
  50. Span<byte> span = new byte[SrcBuffer.Length];
  51. Decode(span);
  52. _decoded = true;
  53. }
  54. /// <summary>
  55. /// 在解码的时候把校验和也计算出来,避免在循环一次进行校验
  56. /// </summary>
  57. /// <returns></returns>
  58. public void Decode(Span<byte> allocateBuffer)
  59. {
  60. int offset = 0;
  61. int len = SrcBuffer.Length;
  62. allocateBuffer[offset++] = SrcBuffer[0];
  63. // 取出校验码看是否需要转义
  64. ReadOnlySpan<byte> checkCodeBufferSpan1 = SrcBuffer.Slice(len - 3, 2);
  65. int checkCodeLen = 0;
  66. if (TryDecode(checkCodeBufferSpan1, out byte value1))
  67. {
  68. //最后两位是转义的
  69. byte[] tmpCrc2 = new byte[2];
  70. checkCodeLen += 2;
  71. tmpCrc2[1] = value1;
  72. //从最后往前在取两位进行转义
  73. ReadOnlySpan<byte> checkCodeBufferSpan2 = SrcBuffer.Slice(len - 5, 2);
  74. if (TryDecode(checkCodeBufferSpan2, out byte value2))
  75. {
  76. //转义成功
  77. tmpCrc2[0] = value2;
  78. checkCodeLen += 2;
  79. }
  80. else
  81. {
  82. //转义不成功取当前最后一位
  83. tmpCrc2[0] = checkCodeBufferSpan2[1];
  84. checkCodeLen += 1;
  85. }
  86. _realCheckCRCCode = ReadUInt16(tmpCrc2);
  87. }
  88. else
  89. {
  90. //最后两位不是转义的
  91. _realCheckCRCCode=ReadUInt16(checkCodeBufferSpan1);
  92. checkCodeLen += 2;
  93. }
  94. //转义数据长度
  95. len = len - checkCodeLen - 1 - 1;
  96. ReadOnlySpan<byte> tmpBufferSpan = SrcBuffer.Slice(1, len);
  97. for (int i = 0; i < tmpBufferSpan.Length; i++)
  98. {
  99. byte tmp = 0;
  100. if ((tmpBufferSpan.Length - i) >= 2)
  101. {
  102. if (TryDecode(tmpBufferSpan.Slice(i, 2), out tmp))
  103. {
  104. i++;
  105. }
  106. }
  107. else
  108. {
  109. tmp = tmpBufferSpan[i];
  110. }
  111. allocateBuffer[offset++] = tmp;
  112. _calculateCheckCRCCode = (ushort)((_calculateCheckCRCCode << 8) ^ (ushort)CRCUtil.CRC[(_calculateCheckCRCCode >> 8) ^ tmp]);
  113. }
  114. allocateBuffer[offset++] = (byte)(_calculateCheckCRCCode >> 8);
  115. allocateBuffer[offset++] = (byte)_calculateCheckCRCCode;
  116. allocateBuffer[offset++] = SrcBuffer[SrcBuffer.Length- 1];
  117. _checkCRCCodeVali = (_calculateCheckCRCCode == _realCheckCRCCode);
  118. Reader = allocateBuffer.Slice(0, offset);
  119. _decoded = true;
  120. }
  121. public void FullDecode()
  122. {
  123. int offset = 0;
  124. Span<byte> span = new byte[SrcBuffer.Length];
  125. int len = SrcBuffer.Length;
  126. for (int i = 0; i < len; i++)
  127. {
  128. byte tmp = 0;
  129. if ((SrcBuffer.Length - i) >= 2)
  130. {
  131. if (TryDecode(SrcBuffer.Slice(i, 2), out tmp))
  132. {
  133. i++;
  134. }
  135. }
  136. else
  137. {
  138. tmp = SrcBuffer[i];
  139. }
  140. span[offset++] = tmp;
  141. }
  142. Reader = span.Slice(0, offset);
  143. }
  144. private bool TryDecode(ReadOnlySpan<byte> buffer,out byte value)
  145. {
  146. if (buffer.SequenceEqual(decode5a01))
  147. {
  148. value = 0x5b;
  149. return true;
  150. }
  151. else if (buffer.SequenceEqual(decode5a02))
  152. {
  153. value = 0x5a;
  154. return true;
  155. }
  156. else if (buffer.SequenceEqual(decode5e01))
  157. {
  158. value = 0x5d;
  159. return true;
  160. }
  161. else if (buffer.SequenceEqual(decode5e02))
  162. {
  163. value = 0x5e;
  164. return true;
  165. }
  166. else
  167. {
  168. value = buffer[0];
  169. return false;
  170. }
  171. }
  172. public ushort CalculateCheckXorCode => _calculateCheckCRCCode;
  173. public ushort RealCheckXorCode => _realCheckCRCCode;
  174. public bool CheckXorCodeVali => _checkCRCCodeVali;
  175. public byte ReadStart()=> ReadByte();
  176. public byte ReadEnd()=> ReadByte();
  177. public ushort ReadUInt16()
  178. {
  179. return BinaryPrimitives.ReadUInt16BigEndian(GetReadOnlySpan(2));
  180. }
  181. public ushort ReadUInt16(ReadOnlySpan<byte> buffer)
  182. {
  183. return BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(0, 2));
  184. }
  185. public uint ReadUInt32()
  186. {
  187. return BinaryPrimitives.ReadUInt32BigEndian(GetReadOnlySpan(4));
  188. }
  189. public int ReadInt32()
  190. {
  191. return BinaryPrimitives.ReadInt32BigEndian(GetReadOnlySpan(4));
  192. }
  193. public ulong ReadUInt64()
  194. {
  195. return BinaryPrimitives.ReadUInt64BigEndian(GetReadOnlySpan(8));
  196. }
  197. public long ReadInt64()
  198. {
  199. return BinaryPrimitives.ReadInt64BigEndian(GetReadOnlySpan(8));
  200. }
  201. public byte ReadByte()
  202. {
  203. return GetReadOnlySpan(1)[0];
  204. }
  205. public byte ReadVirtualByte()
  206. {
  207. return GetVirtualReadOnlySpan(1)[0];
  208. }
  209. public ushort ReadVirtualUInt16()
  210. {
  211. return BinaryPrimitives.ReadUInt16BigEndian(GetVirtualReadOnlySpan(2));
  212. }
  213. public short ReadVirtualInt16()
  214. {
  215. return BinaryPrimitives.ReadInt16BigEndian(GetVirtualReadOnlySpan(2));
  216. }
  217. public uint ReadVirtualUInt32()
  218. {
  219. return BinaryPrimitives.ReadUInt32BigEndian(GetVirtualReadOnlySpan(4));
  220. }
  221. public int ReadVirtualInt32()
  222. {
  223. return BinaryPrimitives.ReadInt32BigEndian(GetVirtualReadOnlySpan(4));
  224. }
  225. public ulong ReadVirtualUInt64()
  226. {
  227. return BinaryPrimitives.ReadUInt64BigEndian(GetVirtualReadOnlySpan(8));
  228. }
  229. public long ReadVirtualInt64()
  230. {
  231. return BinaryPrimitives.ReadInt64BigEndian(GetVirtualReadOnlySpan(8));
  232. }
  233. /// <summary>
  234. /// 数字编码 大端模式、高位在前
  235. /// </summary>
  236. /// <param name="len"></param>
  237. public string ReadBigNumber(int len)
  238. {
  239. ulong result = 0;
  240. var readOnlySpan = GetReadOnlySpan(len);
  241. for (int i = 0; i < len; i++)
  242. {
  243. ulong currentData = (ulong)readOnlySpan[i] << (8 * (len - i - 1));
  244. result += currentData;
  245. }
  246. return result.ToString();
  247. }
  248. public ReadOnlySpan<byte> ReadArray(int len)
  249. {
  250. return GetReadOnlySpan(len).Slice(0, len);
  251. }
  252. public ReadOnlySpan<byte> ReadArray(int start,int end)
  253. {
  254. return Reader.Slice(start,end);
  255. }
  256. public string ReadString(int len)
  257. {
  258. var readOnlySpan = GetReadOnlySpan(len);
  259. string value = JT809Constants.Encoding.GetString(readOnlySpan.Slice(0, len).ToArray());
  260. return value.Trim('\0');
  261. }
  262. public string ReadRemainStringContent()
  263. {
  264. var readOnlySpan = ReadContent(0);
  265. string value = JT809Constants.Encoding.GetString(readOnlySpan.ToArray());
  266. return value.Trim('\0');
  267. }
  268. public string ReadHex(int len)
  269. {
  270. var readOnlySpan = GetReadOnlySpan(len);
  271. string hex = HexUtil.DoHexDump(readOnlySpan, 0, len);
  272. return hex;
  273. }
  274. /// <summary>
  275. /// yyMMddHHmmss
  276. /// </summary>
  277. /// <param name="fromBase">>D2: 10 X2:16</param>
  278. public DateTime ReadDateTime6(string format = "X2")
  279. {
  280. DateTime d;
  281. try
  282. {
  283. var readOnlySpan = GetReadOnlySpan(6);
  284. int year = Convert.ToInt32(readOnlySpan[0].ToString(format)) + JT809Constants.DateLimitYear;
  285. int month = Convert.ToInt32(readOnlySpan[1].ToString(format));
  286. int day = Convert.ToInt32(readOnlySpan[2].ToString(format));
  287. int hour = Convert.ToInt32(readOnlySpan[3].ToString(format));
  288. int minute = Convert.ToInt32(readOnlySpan[4].ToString(format));
  289. int second = Convert.ToInt32(readOnlySpan[5].ToString(format));
  290. d = new DateTime(year, month, day, hour, minute, second);
  291. }
  292. catch (Exception)
  293. {
  294. d = JT809Constants.UTCBaseTime;
  295. }
  296. return d;
  297. }
  298. /// <summary>
  299. /// HH-mm-ss-msms
  300. /// HH-mm-ss-fff
  301. /// </summary>
  302. /// <param name="format">D2: 10 X2:16</param>
  303. public DateTime ReadDateTime5(string format = "X2")
  304. {
  305. DateTime d;
  306. try
  307. {
  308. var readOnlySpan = GetReadOnlySpan(5);
  309. d = new DateTime(
  310. DateTime.Now.Year,
  311. DateTime.Now.Month,
  312. DateTime.Now.Day,
  313. Convert.ToInt32(readOnlySpan[0].ToString(format)),
  314. Convert.ToInt32(readOnlySpan[1].ToString(format)),
  315. Convert.ToInt32(readOnlySpan[2].ToString(format)),
  316. Convert.ToInt32(((readOnlySpan[3] << 8) + readOnlySpan[4])));
  317. }
  318. catch
  319. {
  320. d = JT809Constants.UTCBaseTime;
  321. }
  322. return d;
  323. }
  324. /// <summary>
  325. /// YYYYMMDD
  326. /// </summary>
  327. /// <param name="format">D2: 10 X2:16</param>
  328. public DateTime ReadDateTime4(string format = "X2")
  329. {
  330. DateTime d;
  331. try
  332. {
  333. var readOnlySpan = GetReadOnlySpan(4);
  334. d = new DateTime(
  335. (Convert.ToInt32(readOnlySpan[0].ToString(format)) << 8) + Convert.ToByte(readOnlySpan[1]),
  336. Convert.ToInt32(readOnlySpan[2].ToString(format)),
  337. Convert.ToInt32(readOnlySpan[3].ToString(format)));
  338. }
  339. catch (Exception)
  340. {
  341. d = JT809Constants.UTCBaseTime;
  342. }
  343. return d;
  344. }
  345. public DateTime ReadUTCDateTime()
  346. {
  347. DateTime d;
  348. try
  349. {
  350. ulong result = 0;
  351. var readOnlySpan = GetReadOnlySpan(8);
  352. for (int i = 0; i < 8; i++)
  353. {
  354. ulong currentData = (ulong)readOnlySpan[i] << (8 * (8 - i - 1));
  355. result += currentData;
  356. }
  357. d = JT809Constants.UTCBaseTime.AddSeconds(result).AddHours(8);
  358. }
  359. catch (Exception)
  360. {
  361. d = JT809Constants.UTCBaseTime;
  362. }
  363. return d;
  364. }
  365. public string ReadBCD(int len)
  366. {
  367. int count = len / 2;
  368. var readOnlySpan = GetReadOnlySpan(count);
  369. StringBuilder bcdSb = new StringBuilder(count);
  370. for (int i = 0; i < count; i++)
  371. {
  372. bcdSb.Append(readOnlySpan[i].ToString("X2"));
  373. }
  374. // todo:对于协议来说这个0是有意义的,下个版本在去掉
  375. return bcdSb.ToString().TrimStart('0');
  376. }
  377. private ReadOnlySpan<byte> GetReadOnlySpan(int count)
  378. {
  379. ReaderCount += count;
  380. return Reader.Slice(ReaderCount - count);
  381. }
  382. public ReadOnlySpan<byte> GetVirtualReadOnlySpan(int count)
  383. {
  384. return Reader.Slice(ReaderCount, count);
  385. }
  386. public ReadOnlySpan<byte> ReadContent(int count=0)
  387. {
  388. if (_decoded)
  389. {
  390. //内容长度=总长度-读取的长度-3(校验码1位+终止符1位)
  391. int totalContent = Reader.Length - ReaderCount - 3;
  392. //实际读取内容长度
  393. int realContent = totalContent - count;
  394. int tempReaderCount = ReaderCount;
  395. ReaderCount += realContent;
  396. return Reader.Slice(tempReaderCount, realContent);
  397. }
  398. else
  399. {
  400. return Reader.Slice(ReaderCount);
  401. }
  402. }
  403. public int ReadCurrentRemainContentLength()
  404. {
  405. if (_decoded)
  406. {
  407. //内容长度=总长度-读取的长度-3(校验码2位+终止符1位)
  408. return Reader.Length - ReaderCount - 3;
  409. }
  410. else
  411. {
  412. return Reader.Length - ReaderCount;
  413. }
  414. }
  415. public void Skip(int count=1)
  416. {
  417. ReaderCount += count;
  418. }
  419. }
  420. }