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

904 lines
20 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Runtime.InteropServices;
  6. using System.Diagnostics.Contracts;
  7. using System.Net;
  8. using Gps.Plugin.Common.Helpers;
  9. using System.IO;
  10. using System.Collections;
  11. namespace Gps.Plugin.Tcp.GT808
  12. {
  13. public class PackHelper
  14. {
  15. public static byte[] ToBytes(string deviceId, MessageIds messageId, ushort seqNO, byte[] bodyBytesReturn)
  16. {
  17. HeadPack head = new HeadPack()
  18. {
  19. BodyProp = 0,
  20. MessageId = (ushort)messageId,
  21. SeqNO = seqNO
  22. };
  23. head.SetDeviceId(deviceId);
  24. //BodyPropertyHelper.SetMessageLength(ref head.BodyProp,(ushort)bodyBytesReturn.Length);
  25. BodyPropertyHelper.SetMessageLength(ref head.BodyProp, (ushort)bodyBytesReturn.Length);
  26. return RawFormatter.Instance.Struct2Bytes(head).Concat(bodyBytesReturn).ToArray();
  27. }
  28. public static byte[] DecodeBytes(byte[] buffer)
  29. {
  30. return DecodeBytes(buffer, 0, buffer.Length);
  31. }
  32. public static byte[] DecodeBytes(byte[] bytes, int offset, int length)
  33. {
  34. int index = 0;
  35. int endOffset = Math.Min(length, bytes.Length - offset) + offset;
  36. for (int i = offset; i < endOffset; )
  37. {
  38. if (bytes[i] == 0x7d && bytes[i + 1] == 0x02)
  39. {
  40. bytes[index++] = 0x7e;
  41. i += 2;
  42. }
  43. else if (bytes[i] == 0x7d && bytes[i + 1] == 0x01)
  44. {
  45. bytes[index++] = 0x7d;
  46. i += 2;
  47. }
  48. else
  49. {
  50. bytes[index++] = bytes[i++];
  51. }
  52. }
  53. return bytes.Take(index).ToArray();
  54. }
  55. public static byte[] EncodeBytes(IEnumerable<byte> bytes)
  56. {
  57. MemoryStream ms = new MemoryStream();
  58. foreach (var b in bytes)
  59. {
  60. if (b == 0x7e)
  61. {
  62. ms.WriteByte(0x7d);
  63. ms.WriteByte(0x02);
  64. }
  65. else if (b == 0x7d)
  66. {
  67. ms.WriteByte(0x7d);
  68. ms.WriteByte(0x01);
  69. }
  70. else
  71. {
  72. ms.WriteByte(b);
  73. }
  74. }
  75. return ms.ToArray();
  76. }
  77. /// <summary>
  78. /// 计算校验位
  79. /// </summary>
  80. /// <param name="bytes"></param>
  81. /// <param name="offset"></param>
  82. /// <param name="count"></param>
  83. /// <returns></returns>
  84. public static byte CalcCheckByte(byte[] bytes, int offset, int count)
  85. {
  86. if (count == 0)
  87. return 0;
  88. byte ret = bytes[offset];
  89. for (int i = offset + 1; i < offset + count; ++i)
  90. {
  91. ret ^= bytes[i];
  92. }
  93. return ret;
  94. }
  95. /// <summary>
  96. /// 计算校验位
  97. /// </summary>
  98. /// <param name="bytes"></param>
  99. public static void CalcCheckByte(byte[] bytes)
  100. {
  101. if (bytes.Length == 0)
  102. return;
  103. bytes[bytes.Length - 1] = CalcCheckByte(bytes, 0, bytes.Length - 1);
  104. }
  105. }
  106. /*
  107. 车载GPS定位器通信协议(GT808)(TCP_6004).pdf
  108. P2
  109. *
  110. * 7E-01-02-00-06-00-20-47-05-52-32-00-00-30-31-32-33-34-35-06-7E
  111. */
  112. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  113. public class HeadPack
  114. {
  115. public static byte FixPrefix = 0x7e;
  116. public static Int32 PackSize = Marshal.SizeOf(typeof(HeadPack));
  117. /// <summary>
  118. /// 消息 ID
  119. /// </summary>
  120. public BigEndianUInt16 MessageId;
  121. /// <summary>
  122. /// 消息体属性
  123. /// </summary>
  124. public BigEndianUInt16 BodyProp;
  125. /// <summary>
  126. /// 终端手机号
  127. /// </summary>
  128. protected BCD8421_6BytesString DeviceId;
  129. /// <summary>
  130. /// 自增一序列号
  131. /// </summary>
  132. public BigEndianUInt16 SeqNO;
  133. public string GetDeviceId()
  134. {
  135. return string.Concat("460", DeviceId);
  136. }
  137. public void SetDeviceId(string value)
  138. {
  139. if (value.Length > 12)
  140. {
  141. DeviceId = value.Substring(value.Length - 12, 12);
  142. }
  143. else
  144. {
  145. DeviceId = value.PadLeft(12, '0');
  146. }
  147. }
  148. }
  149. public static class BodyPropertyHelper
  150. {
  151. /// <summary>
  152. /// 9-0 BIT
  153. /// </summary>
  154. /// <param name="val"></param>
  155. /// <returns></returns>
  156. public static Int16 GetMessageLength(BigEndianUInt16 val)
  157. {
  158. return (Int16)((UInt16)val & 0x03ff);
  159. }
  160. /// <summary>
  161. /// 9-0 BIT
  162. /// </summary>
  163. /// <param name="val"></param>
  164. /// <returns></returns>
  165. public static void SetMessageLength(ref BigEndianUInt16 val, UInt16 length)
  166. {
  167. val = (UInt16)(((UInt16)val & (~0x03ff)) + length);
  168. }
  169. /// <summary>
  170. /// 12-10 BIT
  171. /// </summary>
  172. /// <param name="val"></param>
  173. /// <returns></returns>
  174. public static Byte GetEncodeType(BigEndianUInt16 val)
  175. {
  176. return (Byte)((val >> 10) & 0x03);
  177. }
  178. public static void SetEncodeType(ref BigEndianUInt16 val, byte encType)
  179. {
  180. ushort v = val;
  181. v = (ushort)(v & ~(0x03 << 10) + encType << 10);
  182. val = v;
  183. }
  184. /// <summary>
  185. /// 13 BIT
  186. /// </summary>
  187. /// <param name="val"></param>
  188. /// <returns></returns>
  189. public static bool IsMutliPack(this BigEndianUInt16 val)
  190. {
  191. return ((val >> 13) & 0x01) == 0x0001;
  192. }
  193. }
  194. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  195. public class PackProperty
  196. {
  197. public static Int32 PackSize = Marshal.SizeOf(typeof(PackProperty));
  198. public BigEndianUInt16 Total;
  199. public BigEndianUInt16 Index;
  200. }
  201. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  202. public class ServerAnswerPack
  203. {
  204. public static Int32 PackSize = Marshal.SizeOf(typeof(ServerAnswerPack));
  205. /// <summary>
  206. /// 流水
  207. /// </summary>
  208. public BigEndianUInt16 SeqNO;
  209. /// <summary>
  210. /// 消息ID
  211. /// </summary>
  212. public BigEndianUInt16 MessageId;
  213. /// <summary>
  214. /// 结果 0:成功/确认 1:失败 2:消息有误 3:不支持 4:报警处理确认
  215. /// </summary>
  216. public byte Result;
  217. }
  218. /// <summary>
  219. /// 终端通用应答
  220. /// </summary>
  221. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  222. public class ClientAnswerPack
  223. {
  224. public static Int32 PackSize = Marshal.SizeOf(typeof(ServerAnswerPack));
  225. /// <summary>
  226. /// 流水
  227. /// </summary>
  228. public BigEndianUInt16 SeqNO;
  229. /// <summary>
  230. /// 消息ID
  231. /// </summary>
  232. public BigEndianUInt16 MessageId;
  233. /// <summary>
  234. /// 结果 0:成功/确认 1:失败 2:消息有误 3:不支持
  235. /// </summary>
  236. public byte Result;
  237. }
  238. /// <summary>
  239. /// 终端注册 最后是GBK字串,车牌号
  240. /// </summary>
  241. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  242. public class ClientRegistPack
  243. {
  244. public static Int32 PackSize = Marshal.SizeOf(typeof(ClientRegistPack));
  245. /// <summary>
  246. /// 省
  247. /// </summary>
  248. public BigEndianUInt16 Province;
  249. /// <summary>
  250. /// 市
  251. /// </summary>
  252. public BigEndianUInt16 City;
  253. /// <summary>
  254. /// 制造商
  255. /// </summary>
  256. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
  257. public byte[] Manufacturer;
  258. /// <summary>
  259. /// 终端型号
  260. /// </summary>
  261. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
  262. public byte[] DeviceModel;
  263. /// <summary>
  264. /// 终端ID
  265. /// </summary>
  266. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
  267. public byte[] DeviceId;
  268. /// <summary>
  269. /// 车牌颜色
  270. /// </summary>
  271. public byte CarColor;
  272. //最后是GBK字串,车牌号
  273. }
  274. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  275. public class ClientRegistReturnPack
  276. {
  277. /// <summary>
  278. /// 自增一序列号
  279. /// </summary>
  280. public BigEndianUInt16 SeqNum;
  281. /// <summary>
  282. /// 0成功, 1车辆已经注册, 2数据库中无此车辆, 3终端已经被注册, 4数据库中无该终端
  283. /// </summary>
  284. public Byte Result;
  285. }
  286. /// <summary>
  287. /// 位置包汇报
  288. /// </summary>
  289. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  290. public class PositionReportPack
  291. {
  292. public static Int32 PackSize = Marshal.SizeOf(typeof(PositionReportPack));
  293. /// <summary>
  294. /// 报警标志
  295. /// </summary>
  296. public BigEndianUInt32 AlermFlags;
  297. /// <summary>
  298. /// 状态
  299. /// </summary>
  300. public BigEndianUInt32 State;
  301. /// <summary>
  302. /// 纬度 度*10^6
  303. /// </summary>
  304. public BigEndianUInt32 Latitude;
  305. /// <summary>
  306. /// 经度 度*10^6
  307. /// </summary>
  308. public BigEndianUInt32 Longitude;
  309. /// <summary>
  310. /// 高程 单位为米
  311. /// </summary>
  312. public BigEndianUInt16 Altitude;
  313. /// <summary>
  314. /// 速度 1/10KM/H
  315. /// </summary>
  316. public BigEndianUInt16 Speed;
  317. /// <summary>
  318. /// 方向 0~359 正北为0 顺时针
  319. /// </summary>
  320. public BigEndianUInt16 Direction;
  321. /// <summary>
  322. /// 时间
  323. /// </summary>
  324. public BCD8421_6BytesString Time;
  325. }
  326. /// <summary>
  327. /// 立即拍照命令
  328. /// </summary>
  329. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  330. public class CmdPhotographePack
  331. {
  332. /// <summary>
  333. /// 通道ID > 0
  334. /// </summary>
  335. public Byte Channel;
  336. /// <summary>
  337. /// 拍摄命令 0表示停止拍摄;0xffff表示录像;其它表示拍摄张数
  338. /// </summary>
  339. public BigEndianUInt16 Cmd;
  340. /// <summary>
  341. /// 拍照间隔,录像时间。 单位为秒,0表示最小间隔拍照或者一直录像
  342. /// </summary>
  343. public BigEndianUInt16 Interval;
  344. /// <summary>
  345. /// 保存标志 1保存 0立即上传
  346. /// </summary>
  347. public byte Deal;
  348. /// <summary>
  349. /// 图像分辨率 0x01:320*240 0x02:640*480 0x03:800*600 0x04:1024*768
  350. /// 0x05:176*144(Qcif) 0x06:352*288(Cif) 0x07:704*288(HALF D1) 0x08:704*546(D1)
  351. /// </summary>
  352. public byte Resolution;
  353. /// <summary>
  354. /// 图像质量 1 ~ 10 1表示质量损失最小, 10表示压缩最大
  355. /// </summary>
  356. public byte Quality;
  357. /// <summary>
  358. /// 亮度 0 ~ 255
  359. /// </summary>
  360. public byte Brightness;
  361. /// <summary>
  362. /// 对比度 0 ~ 127
  363. /// </summary>
  364. public byte Contrast;
  365. /// <summary>
  366. /// 饱和度 0 ~ 127
  367. /// </summary>
  368. public byte Saturation;
  369. /// <summary>
  370. /// 色度 0 ~ 255
  371. /// </summary>
  372. public byte Chroma;
  373. }
  374. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  375. public class CmdSendTextPack
  376. {
  377. public byte Flag;
  378. /// <summary>
  379. /// 紧急
  380. /// </summary>
  381. public bool IsUrgent
  382. {
  383. get { return (Flag & 0x01) == 0x01; }
  384. set { Flag = (byte)(Flag | 0x01); }
  385. }
  386. /// <summary>
  387. /// 终端显示器显示
  388. /// </summary>
  389. public bool IsDisplay
  390. {
  391. get { return (Flag & 0x04) == 0x04; }
  392. set { Flag = (byte)(Flag | 0x04); }
  393. }
  394. /// <summary>
  395. /// 终端显示器显示
  396. /// </summary>
  397. public bool IsTTS
  398. {
  399. get { return (Flag & 0x08) == 0x08; }
  400. set { Flag = (byte)(Flag | 0x08); }
  401. }
  402. /// <summary>
  403. /// 终端显示器显示
  404. /// </summary>
  405. public bool IsAD
  406. {
  407. get { return (Flag & 0x10) == 0x10; }
  408. set { Flag = (byte)(Flag | 0x10); }
  409. }
  410. //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)]
  411. //public byte[] MessageBytes;
  412. }
  413. /// <summary>
  414. /// 多媒体数据上传
  415. /// </summary>
  416. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  417. public class GpsMultimediaUploadPack
  418. {
  419. public static Int32 PackSize = Marshal.SizeOf(typeof(GpsMultimediaUploadPack));
  420. /// <summary>
  421. /// 多媒体ID >0
  422. /// </summary>
  423. public BigEndianUInt32 ID;
  424. /// <summary>
  425. /// 多媒体类型 0:图像 1:音频 2:视频
  426. /// </summary>
  427. public Byte Type;
  428. /// <summary>
  429. /// 多媒体格式编码 0:JPEG 1:TIF 2:MP3 3:WAV 4:WMV
  430. /// </summary>
  431. public byte Format;
  432. /// <summary>
  433. /// 事件项编码 0:平台下发指令 1:定时动作 2:抢劫报警触发 3:碰撞侧翻触发报警 4:保留
  434. /// </summary>
  435. public byte EventCode;
  436. /// <summary>
  437. /// 通道ID > 0
  438. /// </summary>
  439. public Byte Channel;
  440. }
  441. /// <summary>
  442. /// 多媒体数据上传
  443. /// </summary>
  444. [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  445. public class GpsMultimediaReUploadPack
  446. {
  447. public static Int32 PackSize = Marshal.SizeOf(typeof(GpsMultimediaReUploadPack));
  448. /// <summary>
  449. /// 多媒体ID >0
  450. /// </summary>
  451. public BigEndianUInt32 ID;
  452. /// <summary>
  453. /// 多媒体类型 0:图像 1:音频 2:视频
  454. /// </summary>
  455. public Byte Count;
  456. ///// <summary>
  457. ///// 要求重发的下一个包
  458. ///// </summary>
  459. //public Byte NextIndex;
  460. }
  461. public class BitValueState
  462. {
  463. private BitArray bitArray;
  464. public BitValueState(ushort state)
  465. {
  466. this.bitArray = new BitArray(BitConverter.GetBytes(state));
  467. }
  468. /// <summary>
  469. /// ACC 开关
  470. /// </summary>
  471. bool ACC
  472. {
  473. get
  474. {
  475. return bitArray[0];
  476. }
  477. set
  478. {
  479. bitArray[0] = value;
  480. }
  481. }
  482. /// <summary>
  483. /// 是否定位
  484. /// </summary>
  485. //Position = 0x0002,
  486. bool Position
  487. {
  488. get
  489. {
  490. return bitArray[1];
  491. }
  492. set
  493. {
  494. bitArray[1] = value;
  495. }
  496. }
  497. /// <summary>
  498. /// 0北纬 1南纬
  499. /// </summary>
  500. //NorthOrSouth = 0x0004,
  501. bool IsSouth
  502. {
  503. get
  504. {
  505. return bitArray[2];
  506. }
  507. set
  508. {
  509. bitArray[2] = value;
  510. }
  511. }
  512. /// <summary>
  513. /// 0东经 1西经
  514. /// </summary>
  515. //EastOrWest = 0x0008,
  516. bool IsWest
  517. {
  518. get
  519. {
  520. return bitArray[3];
  521. }
  522. set
  523. {
  524. bitArray[3] = value;
  525. }
  526. }
  527. /// <summary>
  528. /// 0运营状态 1停运
  529. /// </summary>
  530. //OperationState = 0x0010,
  531. bool OperationStoped
  532. {
  533. get
  534. {
  535. return bitArray[4];
  536. }
  537. set
  538. {
  539. bitArray[4] = value;
  540. }
  541. }
  542. /// <summary>
  543. /// 经纬度是否加密
  544. /// </summary>
  545. //EncodeLongitudeLatitude = 0x0020,
  546. bool EncodeLongitudeLatitude
  547. {
  548. get
  549. {
  550. return bitArray[5];
  551. }
  552. set
  553. {
  554. bitArray[5] = value;
  555. }
  556. }
  557. /// <summary>
  558. /// 0车辆油路正常 1断开
  559. /// </summary>
  560. //CarOilchannel = 0x0400,
  561. bool CarOilchannelBreaked
  562. {
  563. get
  564. {
  565. return bitArray[10];
  566. }
  567. set
  568. {
  569. bitArray[10] = value;
  570. }
  571. }
  572. /// <summary>
  573. /// 0车辆电子正常 1断开
  574. /// </summary>
  575. //CarCircuit = 0x0800,
  576. bool CarCircuitBreaked
  577. {
  578. get
  579. {
  580. return bitArray[11];
  581. }
  582. set
  583. {
  584. bitArray[11] = value;
  585. }
  586. }
  587. /// <summary>
  588. /// 0车辆车门解锁 1加锁
  589. /// </summary>
  590. //CarDoorLock = 0x1000
  591. bool CarDoorLocked
  592. {
  593. get
  594. {
  595. return bitArray[12];
  596. }
  597. set
  598. {
  599. bitArray[12] = value;
  600. }
  601. }
  602. }
  603. public class BitValueAlerm
  604. {
  605. //private uint data;
  606. private BitArray bitArray;
  607. public BitValueAlerm(UInt32 alerm)
  608. {
  609. //this.data = alerm;
  610. bitArray = new BitArray(new int[] { (int)alerm });
  611. }
  612. /// <summary>
  613. /// 紧急报警, 触动报警开关后触发 收到答应后清除
  614. /// </summary>
  615. bool Urgent
  616. {
  617. get
  618. {
  619. return bitArray[0];
  620. }
  621. set
  622. {
  623. bitArray[0] = value;
  624. }
  625. }
  626. /// <summary>
  627. /// 超速报警 标志维持到报警条件解除
  628. /// </summary>
  629. bool Speeding
  630. {
  631. get
  632. {
  633. return bitArray[1];
  634. }
  635. set
  636. {
  637. bitArray[1] = value;
  638. }
  639. }
  640. /// <summary>
  641. /// 疲劳驾驶 标志维持到报警条件解除
  642. /// </summary>
  643. bool Fatigue
  644. {
  645. get
  646. {
  647. return bitArray[2];
  648. }
  649. set
  650. {
  651. bitArray[2] = value;
  652. }
  653. }
  654. /// <summary>
  655. /// 预警 收到答应后清除
  656. /// </summary>
  657. bool Forewarning
  658. {
  659. get
  660. {
  661. return bitArray[3];
  662. }
  663. set
  664. {
  665. bitArray[3] = value;
  666. }
  667. }
  668. //TODO:未完, 以后用到添加
  669. }
  670. public enum MessageIds : ushort
  671. {
  672. /// <summary>
  673. /// 终端通用应答
  674. /// </summary>
  675. ClientAnswer = 0x0001,
  676. /// <summary>
  677. /// 终端心跳
  678. /// </summary>
  679. ClientPump = 0x0002,
  680. /// <summary>
  681. /// 终端注销
  682. /// </summary>
  683. ClientUnregist = 0x0003,
  684. /// <summary>
  685. /// 终端注册
  686. /// </summary>
  687. ClientRegist = 0x0100,
  688. /// <summary>
  689. /// 终端鉴权
  690. /// </summary>
  691. ClientAuth = 0x0102,
  692. /// <summary>
  693. /// 位置信息汇报
  694. /// </summary>
  695. PositionReport = 0x0200,
  696. /// <summary>
  697. /// 多媒体事件信息上传
  698. /// </summary>
  699. MultimediaEventUpload = 0x0800,
  700. /// <summary>
  701. /// 多媒体数据上传
  702. /// </summary>
  703. MultimediaUpload = 0x0801,
  704. /// <summary>
  705. /// 多媒体数据上传
  706. /// </summary>
  707. MultimediaUploadAnswer = 0x8800,
  708. /// <summary>
  709. /// 平台通用应答
  710. /// </summary>
  711. ServerAnswer = 0x8001,
  712. /// <summary>
  713. /// 终端注册应答
  714. /// </summary>
  715. ClientRegistReturn = 0x8100,
  716. /// <summary>
  717. /// 立即拍照
  718. /// </summary>
  719. Photographe = 0x8801,
  720. /// <summary>
  721. /// 下发文本
  722. /// </summary>
  723. SendTextMessage = 0x8300
  724. }
  725. }