GT02 协议分析说明及部分实现源代码 (java 版 ) 版本 :1.0 2010.06.21
一收数据部分 服务端收到的都是字节流 ( 字节数组 ), 处理过程中都是 16 进制处理比较方便, 所以要把字节数组转换成 16 进制字符串 使用 Byte2Hex.Bytes2HexString(byte[] readbytes) 将字节数组转换成 16 进制字符串供以后业务流程使用 二收到数据后的解析 (GT02) 得到转换后的 16 进制字符串之后, 按照协议文档, 一个字节一个字节解析即可 GT02 只有两个协议, 是靠协议号来区分的 如果解析到协议号字段是 10 那么就是 GPS 数据, 如果是 1A, 那么是心跳数据包 三终端上来的数据包示例分析 1 GPS 数据包实际例子 686825000003534190318355020002100A0C0E030D190324DCB00CE1F3750000000000000000000 70D0A 分析 : 6868 包头 (2 字节 ) 25 包内容长度 (1 字节 ) 0x25 = 37 0000 保留位 (2 字节 ) 0353419031835502 终端 id(8 字节 ) 即设备 IMEI 号为 353419031835502 0002 信息序列号 (2 字节 ) 10 协议号 (1 字节 ) 0A0C0E030D19 时间 (6 字节 ) 0324DCB0 纬度 (4 字节 ) 计算出来, 纬度为 29.30413 0CE1F375 经度 (4 字节 ) 计算出来, 经度为 120.07473 00 速度 (1 字节 ) 0000 航向 (2 字节 ) 000000 保留位 (3 字节 ) 00000007 状态位 (4 字节 ) 这里 0x07 表示 GPS 已定位, 北纬东经, 未接充电电 源, 非报警状态, 终端正常工作 0D0A 包尾 (2 字节 )
2 心跳数据包实际例子 68681A0604035341903144668018F01A01062D252A25280028001400000D0A 6868 包头 (2 字节 ) 1A 包内容长度 (1 字节 ) 0x1A = 26 06 电压等级 (1 字节 ) 06 04 GSM 信号 (1 字节 ) 04 0353419031446680 终端 id(8 字节 ) 即设备 IMEI 号为 353419031446680 18F0 信息序列号 (2 字节 ) 1A 协议号 (1 字节 ) 01062D252A2528002800140000 卫星信息 (N 字节 ) 0D0A 包尾 (2 字节 ) 四难点 1. 经纬度解析 协议文档上说明了如何由真实经纬度转换成传输的经纬度 所以我们收到转换后的经纬度 (16 进制 ) 后, 进行逆运算即可 具体请参考五包数据解析源代码的经纬度解析 2. 南北纬东西经解析 南北纬东西经在 4 字节的状态位中, 将 16 进制转换成 2 进制后, 对比说明文档即可以知道 GPS 定位状态, 南北纬东西经等, 具体请参考五包数据解析源代码的状态位解析 五包数据解析源代码 // GPS 数据包实际例子 // 686825000003534190318355020002100A0C0E030D190324DCB00CE1F3750000000000000000000 70D0A // 心跳数据包实际例子 // 68681A0604035341903144668018F01A01062D252A25280028001400000D0A // input 即收到的字节数组转换成的 16 进制字符串
// 信息头 (2 字节 ) String xinxitou = input.substring(0, 2 * 2); // 内容长度 (1 字节 ) String neirongchangdu = input.substring(0, 1 * 2); neirongchangdu = Integer.parseInt(neiRongChangDu, 16) + ""; input = input.substring(1 * 2); // 保留位 (2 字节 ) String baoliuwei = input.substring(0, 2 * 2); // imei 号 (trakcer 代号 ) String imei = input.substring(0, 8 * 2); input = input.substring(8 * 2); // 得到 15 位 IMEI 号, 去掉第一个字节 0 imei = imei.substring(1); // 这里可能需要做些 IMEI 号验证, 如当前这个 IMEI 号是否是我们系统里的设备 // 如果不是, 要做些什么处理, 以公司业务决定 // 信息序列号 (2 字节 ) String xuliehao = input.substring(0, 2 * 2); int xuliehaoi = Integer.parseInt(xuLieHao, 16); xuliehao = xuliehaoi + ""; // 协议号 (1 字节 ) String xieyihao = input.substring(0, 1 * 2); input = input.substring(1 * 2); // 如果是心跳数据包, 给予响应 if ("1A".equals(xieYiHao)) { // 设备静止的时候, 只传心跳包, 所以服务端收到心跳包之后 // 要做些业务, 比如, 更新设备的最后连接服务器时间, 表示设备在线等等 // 以公司业务决定 // 注意这里是 16 进制的, 给终端的时候, 发送的是字节流, 要把这 16 进制字符串转换成字节数组 Byte2Hex.HexString2Bytes(String hexstr) return "54681A0D0A";
// 如果不是心跳数据包, 那么就是 GPS 数据包, 下面进行 GPS 数据处理 // 定位时间 (6 字节 ) String datetime = input.substring(0, 6 * 2); if("000000000000".equals(datetime)){ log.error(userid +"--"+username +" 上来的定位时间全是 0"); return null; // 16 进制时间转换成字符串时间 datetime = ProtocolUtil.getSimpleFormatDateTime(dateTime); // 碰到传上来的数据, 有 3 月 32 号的情况 datetime = StringUtil.getStrByDate(StringUtil.getDateByStr(dateTime)); input = input.substring(6 * 2); // 纬度 (4 字节 ) String weidu = input.substring(0, 4 * 2); weidu = new Double(Integer.parseInt(weidu, 16)) / 1800000 + ""; input = input.substring(4 * 2); // 经度 (4 字节 ) String jingdu = input.substring(0, 4 * 2); jingdu = new Double(Integer.parseInt(jingdu, 16)) / 1800000 + ""; input = input.substring(4 * 2); // 速度 (1 字节 ) String sudu = input.substring(0, 1 * 2); int isudu = Integer.parseInt(suDu, 16); sudu = isudu + ""; input = input.substring(1 * 2); // 航向 (2 字节 ) String hangxiang = input.substring(0, 2 * 2); hangxiang = Integer.parseInt(hangXiang, 16) + ""; // 保留字节 (3 字节 ) String baoliuzijie = input.substring(0, 3 * 2); input = input.substring(3 * 2); // 状态位 (4 字节 ) String zhuangtaiwei = input.substring(0, 4 * 2); input = input.substring(4 * 2); // 4 个字节,32 位
String bytestatus = ProtocolUtil.str2ByteString(zhuangTaiWei, 32); // 东西经标志位 String jing = bytestatus.substring(29, 30); // 0 表示西经, 负数 if ("0".equals(jing)) { jingdu = "-" + jingdu; // 南北纬标志位 String wei = bytestatus.substring(30, 31); // 0 表示南纬, 负数 if ("0".equals(wei)) { weidu = "-" + weidu; // 到这里 GPS 数据包解析完毕, 接下来数据是写进数据库呢还是啥的自己决定 六引用代码 里面用到的类和方法如下 : ProtocolUtil.java StringUtil.java Byte2Hex.java 请自行参考