Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

419 wiersze
21 KiB

  1. using JT808.Protocol.Enums;
  2. using JT808.Protocol.Exceptions;
  3. using JT808.Protocol.Extensions;
  4. using JT808.Protocol.Formatters;
  5. using JT808.Protocol.Interfaces;
  6. using JT808.Protocol.MessagePack;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text.Json;
  11. namespace JT808.Protocol.MessageBody
  12. {
  13. /// <summary>
  14. /// 位置信息汇报
  15. /// </summary>
  16. public class JT808_0x0200 : JT808Bodies, IJT808MessagePackFormatter<JT808_0x0200>, IJT808Analyze
  17. {
  18. /// <summary>
  19. /// 0x0200
  20. /// </summary>
  21. public override ushort MsgId { get; } = 0x0200;
  22. /// <summary>
  23. /// 位置信息汇报
  24. /// </summary>
  25. public override string Description => "位置信息汇报";
  26. /// <summary>
  27. /// 报警标志
  28. /// <see cref="JT808.Protocol.Enums.JT808Alarm"/>
  29. /// </summary>
  30. public uint AlarmFlag { get; set; }
  31. /// <summary>
  32. /// 状态位标志
  33. /// <see cref="JT808.Protocol.Enums.JT808Status"/>
  34. /// </summary>
  35. public uint StatusFlag { get; set; }
  36. /// <summary>
  37. /// 纬度
  38. /// 以度为单位的纬度值乘以 10 的 6 次方,精确到百万分之一度
  39. /// </summary>
  40. public int Lat { get; set; }
  41. /// <summary>
  42. /// 经度
  43. /// 以度为单位的经度值乘以 10 的 6 次方,精确到百万分之一度
  44. /// </summary>
  45. public int Lng { get; set; }
  46. /// <summary>
  47. /// 高程
  48. /// 海拔高度,单位为米(m)
  49. /// </summary>
  50. public ushort Altitude { get; set; }
  51. /// <summary>
  52. /// 速度 1/10km/h
  53. /// </summary>
  54. public ushort Speed { get; set; }
  55. /// <summary>
  56. /// 方向 0-359,正北为 0,顺时针
  57. /// </summary>
  58. public ushort Direction { get; set; }
  59. /// <summary>
  60. /// YY-MM-DD-hh-mm-ss(GMT+8 时间,本标准中之后涉及的时间均采用此时区)
  61. /// </summary>
  62. public DateTime GPSTime { get; set; }
  63. /// <summary>
  64. /// 位置附加信息
  65. /// </summary>
  66. public Dictionary<byte, JT808_0x0200_BodyBase> JT808LocationAttachData { get; set; }
  67. /// <summary>
  68. /// 存储未知的附加信息源数据
  69. /// </summary>
  70. public Dictionary<byte, byte[]> JT808UnknownLocationAttachOriginalData { get; set; }
  71. /// <summary>
  72. /// 自定义位置附加信息
  73. /// 场景:
  74. /// 一个设备厂商对应多个设备类型,不同设备类型可能存在相同的自定义位置附加信息Id,导致自定义附加信息Id冲突,无法解析。
  75. /// 解决方式:
  76. /// 1.凡是解析自定义附加信息Id协议的,先进行分割存储,然后在根据外部的设备类型进行统一处理。
  77. /// 2.可以根据设备类型做个工厂,解耦对公共序列化器的依赖。
  78. /// 缺点:
  79. /// 依赖平台录入的设备类型
  80. /// </summary>
  81. public Dictionary<byte, JT808_0x0200_CustomBodyBase> JT808CustomLocationAttachData { get; set; }
  82. /// <summary>
  83. ///
  84. /// </summary>
  85. /// <param name="reader"></param>
  86. /// <param name="config"></param>
  87. /// <returns></returns>
  88. public JT808_0x0200 Deserialize(ref JT808MessagePackReader reader, IJT808Config config)
  89. {
  90. JT808_0x0200 jT808_0X0200 = new JT808_0x0200();
  91. jT808_0X0200.AlarmFlag = reader.ReadUInt32();
  92. jT808_0X0200.StatusFlag = reader.ReadUInt32();
  93. if (((jT808_0X0200.StatusFlag >> 28) & 1) == 1)
  94. { //南纬 268435456 0x10000000
  95. jT808_0X0200.Lat = (int)reader.ReadUInt32();
  96. }
  97. else
  98. {
  99. jT808_0X0200.Lat = reader.ReadInt32();
  100. }
  101. if (((jT808_0X0200.StatusFlag >> 27) & 1) == 1)
  102. { //西经 ‭134217728‬ 0x8000000
  103. jT808_0X0200.Lng = (int)reader.ReadUInt32();
  104. }
  105. else
  106. {
  107. jT808_0X0200.Lng = reader.ReadInt32();
  108. }
  109. jT808_0X0200.Altitude = reader.ReadUInt16();
  110. jT808_0X0200.Speed = reader.ReadUInt16();
  111. jT808_0X0200.Direction = reader.ReadUInt16();
  112. jT808_0X0200.GPSTime = reader.ReadDateTime6();
  113. // 位置附加信息
  114. jT808_0X0200.JT808LocationAttachData = new Dictionary<byte, JT808_0x0200_BodyBase>();
  115. jT808_0X0200.JT808CustomLocationAttachData = new Dictionary<byte, JT808_0x0200_CustomBodyBase>();
  116. jT808_0X0200.JT808UnknownLocationAttachOriginalData = new Dictionary<byte, byte[]>();
  117. while (reader.ReadCurrentRemainContentLength() > 0)
  118. {
  119. try
  120. {
  121. ReadOnlySpan<byte> attachSpan = reader.GetVirtualReadOnlySpan(2);
  122. byte attachId = attachSpan[0];
  123. byte attachLen = attachSpan[1];
  124. if (config.JT808_0X0200_Factory.Map.TryGetValue(attachId, out object jT808LocationAttachInstance))
  125. {
  126. dynamic attachImpl = JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(jT808LocationAttachInstance, ref reader, config);
  127. jT808_0X0200.JT808LocationAttachData.Add(attachImpl.AttachInfoId, attachImpl);
  128. }
  129. else if (config.JT808_0X0200_Custom_Factory.Map.TryGetValue(attachId,out object customAttachInstance))
  130. {
  131. dynamic attachImpl = JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(customAttachInstance, ref reader, config);
  132. jT808_0X0200.JT808CustomLocationAttachData.Add(attachImpl.AttachInfoId, attachImpl);
  133. }
  134. else
  135. {
  136. reader.Skip(2);
  137. jT808_0X0200.JT808UnknownLocationAttachOriginalData.Add(attachId, reader.ReadArray(reader.ReaderCount - 2, attachLen + 2).ToArray());
  138. reader.Skip(attachLen);
  139. }
  140. }
  141. catch
  142. {
  143. try
  144. {
  145. byte attachId = reader.ReadByte();
  146. byte attachLen = reader.ReadByte();
  147. jT808_0X0200.JT808UnknownLocationAttachOriginalData.Add(attachId, reader.ReadArray(reader.ReaderCount - 2, attachLen + 2).ToArray());
  148. reader.Skip(attachLen);
  149. }
  150. catch (Exception ex)
  151. {
  152. throw;
  153. }
  154. }
  155. }
  156. return jT808_0X0200;
  157. }
  158. /// <summary>
  159. ///
  160. /// </summary>
  161. /// <param name="writer"></param>
  162. /// <param name="value"></param>
  163. /// <param name="config"></param>
  164. public void Serialize(ref JT808MessagePackWriter writer, JT808_0x0200 value, IJT808Config config)
  165. {
  166. writer.WriteUInt32(value.AlarmFlag);
  167. writer.WriteUInt32(value.StatusFlag);
  168. //0x10000000 南纬 134217728
  169. //0x8000000 西经 ‭‬268435456
  170. //0x18000000 南纬-西经 134217728+268435456
  171. if (((value.StatusFlag >> 28) & 1) == 1)
  172. {
  173. uint lat = (uint)value.Lat;
  174. writer.WriteUInt32(lat);
  175. }
  176. else
  177. {
  178. if (value.Lat < 0)
  179. {
  180. throw new JT808Exception(JT808ErrorCode.LatOrLngError, $"Lat {nameof(JT808_0x0200.StatusFlag)} ({value.StatusFlag}>>28) !=1");
  181. }
  182. writer.WriteInt32(value.Lat);
  183. }
  184. if (((value.StatusFlag >> 27) & 1) == 1)
  185. {
  186. uint lng = (uint)value.Lng;
  187. writer.WriteUInt32(lng);
  188. }
  189. else
  190. {
  191. if (value.Lng < 0)
  192. {
  193. throw new JT808Exception(JT808ErrorCode.LatOrLngError, $"Lng {nameof(JT808_0x0200.StatusFlag)} ({value.StatusFlag}>>29) !=1");
  194. }
  195. writer.WriteInt32(value.Lng);
  196. }
  197. writer.WriteUInt16(value.Altitude);
  198. writer.WriteUInt16(value.Speed);
  199. writer.WriteUInt16(value.Direction);
  200. writer.WriteDateTime6(value.GPSTime);
  201. if (value.JT808LocationAttachData != null && value.JT808LocationAttachData.Count > 0)
  202. {
  203. foreach (var item in value.JT808LocationAttachData)
  204. {
  205. try
  206. {
  207. JT808MessagePackFormatterResolverExtensions.JT808DynamicSerialize(item.Value, ref writer, item.Value, config);
  208. }
  209. catch(Exception ex)
  210. {
  211. }
  212. }
  213. }
  214. if (value.JT808CustomLocationAttachData != null && value.JT808CustomLocationAttachData.Count > 0)
  215. {
  216. foreach (var item in value.JT808CustomLocationAttachData)
  217. {
  218. JT808MessagePackFormatterResolverExtensions.JT808DynamicSerialize(item.Value, ref writer, item.Value, config);
  219. }
  220. }
  221. }
  222. /// <summary>
  223. ///
  224. /// </summary>
  225. /// <param name="reader"></param>
  226. /// <param name="writer"></param>
  227. /// <param name="config"></param>
  228. public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config)
  229. {
  230. JT808_0x0200 value = new JT808_0x0200();
  231. value.AlarmFlag = reader.ReadUInt32();
  232. writer.WriteNumber($"[{value.AlarmFlag.ReadBinary().ToString()}]报警标志", value.AlarmFlag);
  233. value.StatusFlag = reader.ReadUInt32();
  234. var alarmFlagBits =Convert.ToString(value.AlarmFlag, 2).PadLeft(32, '0').AsSpan();
  235. writer.WriteStartObject("报警标志对象");
  236. if (reader.Version == JT808Version.JTT2019)
  237. {
  238. writer.WriteString($"[bit31]保留", $"{alarmFlagBits[0]}");
  239. }
  240. else
  241. {
  242. writer.WriteString($"[bit31]非法开门报警", $"{alarmFlagBits[0]}");
  243. }
  244. writer.WriteString($"[bit30]侧翻预警", $"{alarmFlagBits[1]}");
  245. writer.WriteString($"[bit29]碰撞预警", $"{alarmFlagBits[2]}");
  246. writer.WriteString($"[bit28]车辆非法位移", $"{alarmFlagBits[3]}");
  247. writer.WriteString($"[bit27]车辆非法点火", $"{alarmFlagBits[4]}");
  248. writer.WriteString($"[bit26]车辆被盗(通过车辆防盗器)", $"{alarmFlagBits[5]}");
  249. writer.WriteString($"[bit25]车辆油量异常", $"{alarmFlagBits[6]}");
  250. writer.WriteString($"[bit24]车辆VSS故障", $"{alarmFlagBits[7]}");
  251. writer.WriteString($"[bit23]路线偏离报警", $"{alarmFlagBits[8]}");
  252. writer.WriteString($"[bit22]路段行驶时间不足/过长", $"{alarmFlagBits[9]}");
  253. writer.WriteString($"[bit21]进出路线", $"{alarmFlagBits[10]}");
  254. writer.WriteString($"[bit20]进出区域", $"{alarmFlagBits[11]}");
  255. writer.WriteString($"[bit19]超时停车", $"{alarmFlagBits[12]}");
  256. writer.WriteString($"[bit18]当天累计驾驶超时", $"{alarmFlagBits[13]}");
  257. if (reader.Version == JT808Version.JTT2019)
  258. {
  259. writer.WriteString($"[bit17]右转盲区异常报警", $"{alarmFlagBits[14]}");
  260. writer.WriteString($"[bit16]胎压预警", $"{alarmFlagBits[15]}");
  261. writer.WriteString($"[bit15]违规行驶报警", $"{alarmFlagBits[16]}");
  262. }
  263. else
  264. {
  265. writer.WriteString($"[bit15~bit17]保留", alarmFlagBits.Slice(14, 3).ToString());
  266. }
  267. writer.WriteString($"[bit14]疲劳驾驶预警", $"{alarmFlagBits[17]}");
  268. writer.WriteString($"[bit13]超速预警", $"{alarmFlagBits[18]}");
  269. writer.WriteString($"[bit12]道路运输证IC卡模块故障", $"{alarmFlagBits[19]}");
  270. writer.WriteString($"[bit11]摄像头故障", $"{alarmFlagBits[20]}");
  271. writer.WriteString($"[bit10]TTS模块故障", $"{alarmFlagBits[21]}");
  272. writer.WriteString($"[bit9]终端LCD或显示器故障", $"{alarmFlagBits[22]}");
  273. writer.WriteString($"[bit8]终端主电源掉电", $"{alarmFlagBits[23]}");
  274. writer.WriteString($"[bit7]终端主电源欠压", $"{alarmFlagBits[24]}");
  275. writer.WriteString($"[bit6]GNSS天线短路", $"{alarmFlagBits[25]}");
  276. writer.WriteString($"[bit5]GNSS天线未接或被剪断", $"{alarmFlagBits[26]}");
  277. writer.WriteString($"[bit4]GNSS模块发生故障", $"{alarmFlagBits[27]}");
  278. writer.WriteString($"[bit3]危险预警", $"{alarmFlagBits[28]}");
  279. writer.WriteString($"[bit2]疲劳驾驶", $"{alarmFlagBits[29]}");
  280. writer.WriteString($"[bit1]超速报警", $"{alarmFlagBits[30]}");
  281. writer.WriteString($"[bit0]紧急报警,触动报警开关后触发", $"{alarmFlagBits[31]}");
  282. writer.WriteEndObject();
  283. writer.WriteNumber($"[{value.StatusFlag.ReadBinary().ToString()}]状态位标志", value.StatusFlag);
  284. var StatusFlagBits = Convert.ToString(value.StatusFlag, 2).PadLeft(32, '0').AsSpan();
  285. writer.WriteStartObject("状态标志对象");
  286. if (reader.Version == JT808Version.JTT2019)
  287. {
  288. writer.WriteString($"[bit23~bit31]保留", StatusFlagBits.Slice(0, 9).ToString());
  289. writer.WriteString($"[{StatusFlagBits[9]}]bit22", StatusFlagBits[9] == '0' ? "车辆处于停止状态" : "车辆处于行驶状态");
  290. }
  291. else
  292. {
  293. writer.WriteString($"[bit22~bit31]保留", StatusFlagBits.Slice(0, 10).ToString());
  294. }
  295. writer.WriteString($"[{StatusFlagBits[10]}]bit21", StatusFlagBits[10] == '0' ? "未使用Galileo卫星进行定位" : "使用Galileo卫星进行定位");
  296. writer.WriteString($"[{StatusFlagBits[11]}]bit20", StatusFlagBits[11] == '0' ? "未使用GLONASS卫星进行定位" : "使用GLONASS卫星进行定位");
  297. writer.WriteString($"[{StatusFlagBits[12]}]bit19", StatusFlagBits[12] == '0' ? "未使用北斗卫星进行定位" : "使用北斗卫星进行定位");
  298. writer.WriteString($"[{StatusFlagBits[13]}]bit18", StatusFlagBits[13] == '0' ? "未使用GPS卫星进行定位" : "使用GPS卫星进行定位");
  299. writer.WriteString($"[{StatusFlagBits[14]}]bit17", StatusFlagBits[14] == '0' ? "门5关" : "门5开");
  300. writer.WriteString($"[{StatusFlagBits[15]}]bit16", StatusFlagBits[15] == '0' ? "门4关" : "门4开");
  301. writer.WriteString($"[{StatusFlagBits[16]}]bit15", StatusFlagBits[16] == '0' ? "门3关" : "门3开");
  302. writer.WriteString($"[{StatusFlagBits[17]}]bit14", StatusFlagBits[17] == '0' ? "门2关" : "门2开");
  303. writer.WriteString($"[{StatusFlagBits[18]}]bit13", StatusFlagBits[18] == '0' ? "门1关" : "门1开");
  304. writer.WriteString($"[{StatusFlagBits[19]}]bit12", StatusFlagBits[19] == '0' ? "车门解锁" : "车门加锁");
  305. writer.WriteString($"[{StatusFlagBits[20]}]bit11", StatusFlagBits[20] == '0' ? "车辆电路正常" : "车辆电路断开");
  306. writer.WriteString($"[{StatusFlagBits[21]}]bit10", StatusFlagBits[21] == '0' ? "车辆油路正常" : "车辆油路断开");
  307. var bit8And9 = StatusFlagBits.Slice(22, 2).ToString();
  308. switch (bit8And9)
  309. {
  310. case "00":
  311. writer.WriteString($"[{bit8And9}]bit8~bit9", "空车");
  312. break;
  313. case "01":
  314. writer.WriteString($"[{bit8And9}]bit8~bit9", "半载");
  315. break;
  316. case "10":
  317. writer.WriteString($"[{bit8And9}]bit8~bit9", "保留");
  318. break;
  319. case "11":
  320. writer.WriteString($"[{bit8And9}]bit8~bit9", "满载");
  321. break;
  322. }
  323. writer.WriteString($"[bit6~bit7]保留", StatusFlagBits.Slice(24, 2).ToString());
  324. writer.WriteString($"[{StatusFlagBits[26]}]bit5", StatusFlagBits[26] == '0' ? "经纬度未经保密插件加密" : "经纬度已经保密插件加密");
  325. writer.WriteString($"[{StatusFlagBits[27]}]bit4", StatusFlagBits[27] == '0' ? "运营状态" : "停运状态");
  326. writer.WriteString($"[{StatusFlagBits[28]}]bit3", StatusFlagBits[28] == '0' ? "东经" : "西经");
  327. writer.WriteString($"[{StatusFlagBits[29]}]bit2", StatusFlagBits[29] == '0' ? "北纬" : "南纬");
  328. writer.WriteString($"[{StatusFlagBits[30]}]bit1", StatusFlagBits[30] == '0' ? "未定位" : "定位");
  329. writer.WriteString($"[{StatusFlagBits[31]}]bit0", StatusFlagBits[31] == '0' ? "ACC关" : "ACC开");
  330. writer.WriteEndObject();
  331. if (((value.StatusFlag >> 28) & 1) == 1)
  332. { //南纬 268435456 0x10000000
  333. value.Lat = (int)reader.ReadUInt32();
  334. writer.WriteNumber($"[{value.Lat.ReadNumber()}]纬度", value.Lat);
  335. }
  336. else
  337. {
  338. value.Lat = reader.ReadInt32();
  339. writer.WriteNumber($"[{value.Lat.ReadNumber()}]纬度", value.Lat);
  340. }
  341. if (((value.StatusFlag >> 27) & 1) == 1)
  342. { //西经 ‭134217728‬ 0x8000000
  343. value.Lng = (int)reader.ReadUInt32();
  344. writer.WriteNumber($"[{value.Lng.ReadNumber()}]经度", value.Lng);
  345. }
  346. else
  347. {
  348. value.Lng = reader.ReadInt32();
  349. writer.WriteNumber($"[{value.Lng.ReadNumber()}]经度", value.Lng);
  350. }
  351. value.Altitude = reader.ReadUInt16();
  352. writer.WriteNumber($"[{value.Altitude.ReadNumber()}]高程", value.Altitude);
  353. value.Speed = reader.ReadUInt16();
  354. writer.WriteNumber($"[{value.Speed.ReadNumber()}]速度", value.Speed);
  355. value.Direction = reader.ReadUInt16();
  356. writer.WriteNumber($"[{value.Direction.ReadNumber()}]方向", value.Direction);
  357. value.GPSTime = reader.ReadDateTime6();
  358. writer.WriteString($"[{value.GPSTime.ToString("yyMMddHHmmss")}]定位时间", value.GPSTime.ToString("yyyy-MM-dd HH:mm:ss"));
  359. // 位置附加信息
  360. writer.WriteStartArray("附加信息列表");
  361. while (reader.ReadCurrentRemainContentLength() > 0)
  362. {
  363. try
  364. {
  365. ReadOnlySpan<byte> attachSpan = reader.GetVirtualReadOnlySpan(2);
  366. byte attachId = attachSpan[0];
  367. byte attachLen = attachSpan[1];
  368. if (config.JT808_0X0200_Factory.Map.TryGetValue(attachId, out object jT808LocationAttachInstance))
  369. {
  370. writer.WriteStartObject();
  371. jT808LocationAttachInstance.Analyze(ref reader, writer, config);
  372. writer.WriteEndObject();
  373. }
  374. else if (config.JT808_0X0200_Custom_Factory.Map.TryGetValue(attachId, out object customAttachInstance))
  375. {
  376. writer.WriteStartObject();
  377. customAttachInstance.Analyze(ref reader, writer, config);
  378. writer.WriteEndObject();
  379. }
  380. else
  381. {
  382. writer.WriteStartObject();
  383. reader.Skip(2);
  384. writer.WriteNumber($"[{attachId.ReadNumber()}]未知附加信息Id", attachId);
  385. writer.WriteNumber($"[{attachLen.ReadNumber()}]未知附加信息长度", attachLen);
  386. writer.WriteString($"未知附加信息", reader.ReadArray(reader.ReaderCount - 2, attachLen + 2).ToArray().ToHexString());
  387. reader.Skip(attachLen);
  388. writer.WriteEndObject();
  389. }
  390. }
  391. catch
  392. {
  393. writer.WriteStartObject();
  394. try
  395. {
  396. byte attachId = reader.ReadByte();
  397. byte attachLen = reader.ReadByte();
  398. writer.WriteNumber($"[{attachId.ReadNumber()}]未知附加信息Id", attachId);
  399. writer.WriteNumber($"[{attachLen.ReadNumber()}]未知附加信息长度", attachLen);
  400. writer.WriteString($"未知附加信息", reader.ReadArray(reader.ReaderCount - 2, attachLen + 2).ToArray().ToHexString());
  401. reader.Skip(attachLen);
  402. }
  403. catch (Exception ex)
  404. {
  405. throw;
  406. }
  407. finally
  408. {
  409. writer.WriteEndObject();
  410. }
  411. }
  412. }
  413. writer.WriteEndArray();
  414. }
  415. }
  416. }