Ver Fonte

bugfix: 慷慨斯GK309设备添加报警回复

如果服务端不对报警信息进行回复,部分设备端会不停的重启。添加该类型的回复
vinson há 5 anos atrás
pai
commit
13f648510b

+ 151 - 42
src/main/java/com/tidecloud/dataacceptance/service/impl/GK309GpsServerHandler.java

@@ -1,8 +1,6 @@
 package com.tidecloud.dataacceptance.service.impl;
 
 import com.accept.client.DeviceMsgClient;
-import com.accept.model.DeviceMsgDto;
-import com.smartsanitation.common.util.StringUtil;
 import com.tidecloud.dataacceptance.codec.HeaderTailDelimiterFrameDecoder;
 import com.tidecloud.dataacceptance.common.*;
 import com.tidecloud.dataacceptance.entity.YiTongGPSDevice;
@@ -55,6 +53,8 @@ public class GK309GpsServerHandler extends HexBinaryAcceptanceHandlerAdapter {
     private static final byte LOGIN_MSG = 0x01;// 登录 (必须回复)
     private static final byte STATUS_MSG = 0x13;// 心跳,状态信息包  (必须回复)
     private static final byte LOCATION_MSG = 0x10;// 一般GPS 位置信息上传
+    private static final byte GPS_WARN = 0x16;// 一般GPS 位置信息上传
+    private static final byte LBS_WARN = 0x19;// 一般GPS 位置信息上传
     private static final byte CORRECT_TIME_MSG = 0x1F;// 校验时间
     private static final byte SIGN_IN_MSG = (byte)0xB0;// 打卡
 
@@ -70,6 +70,21 @@ public class GK309GpsServerHandler extends HexBinaryAcceptanceHandlerAdapter {
     @Autowired
     private DeviceMsgClient deviceMsgClient;
 
+    /**
+     * <b>协议格式:</b>
+     *  <p>起始位 2位
+     *  <p>包长度 1位 :协议号+信息内容+信息序列号+错误校验
+     *  <p>协议号 1位
+     *  <p>信息内容 看每个协议的规定
+     *  <p>信息序列号 2位
+     *  <p>错误校验 2位
+     *  <p>停止位 2位
+     *  <p></p>
+     * <p>本方法把起始位去掉,拿出包长度和剩下的部分调用{@link #handle(ByteBuf, int, Channel)} 方法
+     * @param in
+     * @param channel
+     * @throws Exception
+     */
     @Override
     protected void handle(ByteBuf in, Channel channel) throws Exception {
         if (in.isReadable()) {
@@ -98,6 +113,13 @@ public class GK309GpsServerHandler extends HexBinaryAcceptanceHandlerAdapter {
         }
     }
 
+    /**
+     * 根据协议号处理每个指令
+     * @param in 协议号及其后面的报文组成的byteBuf
+     * @param length 协议长度
+     * @param channel
+     * @throws Exception
+     */
     private void handle(ByteBuf in, int length, Channel channel) throws Exception {
         if (in.isReadable()) {
             byte msgType = in.readByte();// 协议号 1个字节
@@ -135,53 +157,129 @@ public class GK309GpsServerHandler extends HexBinaryAcceptanceHandlerAdapter {
 //                reply(channel, CORRECT_TIME_MSG, "校时包");
                 replyForTime(channel, ret);
             } else if (SIGN_IN_MSG == msgType) {
-                byte[] dataBytes = new byte[6];
-                in.readBytes(dataBytes);
-
-                in.skipBytes(1);
-                byte[] reservedWorkBytes = new byte[2];
-                in.readBytes(reservedWorkBytes);
-
-                // 根据文档查看上下班标示
-                ByteBuf byteBuf = null;
-                byte b;
-                try {
-                    byteBuf = in.readBytes(13);
-                    byteBuf.skipBytes(12);
-                    b = byteBuf.readByte();
-                } finally {
-                    if (byteBuf != null) {
-                        byteBuf.release();
-                    }
-                }
-                // 2-5位代表是上班还是下班
-                byte i = (byte) (b & MARK);
+                replayForSignIn(in, length, channel);
+            } else if(GPS_WARN == msgType) {
+                replyGpsWarn(channel);
+            } else if (LBS_WARN == msgType) {
+                replyLbsWarn(channel);
+            } else {
+                logger.info("client send data without handle type ...");
+            }
+        }
 
-//                类型: 1(上班), 2(下班)
-                Byte signResponse = null;
-                if (i == SIGN_IN) {
-                    signResponse = 0X01;
-                } else {
-                    signResponse = 0x02;
-                }
+    }
+
+    /**
+     * 对于报警消息,设备端能够拿到经纬度信息,但是拿不到地址信息,所以需要服务端根据消息体中的经纬度回复对应的
+     * 地址信息。在太的的使用场景中,不会使用到这个地址,<b>所以目前的做法是回复一个固定的地址,,只有序列号是变化的。</b>
+     * <p>
+     * <p>按照一下示例进行回复的:
+     * <p>设备上传:78 78 25 16 14 03 0B 0F 12 12 CC 02 6C 19 06 0C 38 D1 92 00 15 45 09 01 CC 00 28 66 00 0F 6F 20 03 04 00
+     * 01 00 0C 8C CA 0D 0A
+     * <p>平台回复:78 78 76 16 70 36 4E 55 30 41 44 44 52 45 53 53 26 26 00 53 00 4F 00 53 62 A5 8B 66 00 3A 5E 7F 4E 1C 77
+     * 01 6D F1 57 33 5E 02 5B 9D 5B 89 53 3A 96 86 66 0C 8D EF 00 32 00 2C 9A D8 65 B0 59 47 79 D1 62 80 56 ED 4E 1C
+     * 53 57 00 33 00 34 7C 73 FF 08 7C BE 78 6E 5B 9A 4F 4D FF 09 26 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+     * 00 00 00 00 00 00 23 23 00 0C 23 04 0D 0A
+     */
+    private void replyGpsWarn(Channel channel) {
+        byte[] contentToReply = new byte[]{0x76, 0x16, 0x70, 0x36, 0x4E, 0x55, 0x30, 0x41, 0x44, 0x44,
+                0x52, 0x45, 0x53, 0x53, 0x26, 0x26, 0x00, 0x53, 0x00, 0x4F, 0x00, 0x53, 0x62, (byte) 0xA5,
+                (byte) 0x8B, 0x66, 0x00,
+                0x3A, 0x5E, 0x7F, 0x4E, 0x1C, 0x77, 0x01, 0x6D, (byte) 0xF1, 0x57, 0x33, 0x5E, 0x02, 0x5B,
+                (byte) 0x9D, 0x5B, (byte) 0x89,
+                0x53, 0x3A, (byte) 0x96, (byte) 0x86, 0x66, 0x0C, (byte) 0x8D, (byte) 0xEF, 0x00, 0x32, 0x00, 0x2C,
+                (byte) 0x9A, (byte) 0xD8, 0x65, (byte) 0xB0,
+                0x59,
+                0x47, 0x79, (byte) 0xD1, 0x62, (byte) 0x80, 0x56, (byte) 0xED, 0x4E, 0x1C, 0x53, 0x57, 0x00, 0x33,
+                0x00, 0x34, 0x7C, 0x73,
+                (byte) 0xFF, 0x08, 0x7C, (byte) 0xBE, 0x78, 0x6E, 0x5B, (byte) 0x9A, 0x4F, 0x4D, (byte) 0xFF, 0x09,
+                0x26, 0x26, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x23, 0x23, 0x00, 0x0C};
+        writeToClient(channel, "GPS报警报", contentToReply);
+    }
 
-                // 减去前面跳过的第一位和前面跳过的7位,再减去最后的四位(序列号本身的2位+校验位2位)
-                in.skipBytes(length - 8 - 2 - 2 - 15);
-                short serNum = in.readShort();
-                byte[] serNumBytes = short2Bytes(serNum);
+    /**
+     * 对于报警消息,设备端能够拿到经纬度信息,但是拿不到地址信息,所以需要服务端根据消息体中的经纬度回复对应的
+     * 地址信息。在太的的使用场景中,不会使用到这个地址,<b>所以目前的做法是回复一个固定的地址,,只有序列号是变化的。</b>
+     * <p>
+     * <p>按照一下示例进行回复的:
+     * <p>LBS.状态包(终端?服务器):
+     * <p>78 78 12 19 01 CC 00 28 66 00 0E EE 20 05 04 00 01 00 14 50 0C 0D 0A
+     * <p>服务器回复(服务器?终端):
+     * <p>紧 急 呼 叫 : 广 东 省 . 深 圳 市 . 宝 安 区 边 检 路 . 甲 岸 科 技 园 附 近 . 同 乐 出 口 附
+     * <p>近.(N22.575,E113.917)附近
+     * <p>78 78 9A 17 94 00 00 00 01 41 44 44 52 45 53 53 26 26 7D 27 60 25 54 7C 53 EB 00
+     * <p>3A 5E 7F 4E 1C 77 01 00 2E 6D F1 57 33 5E 02 00 2E 5B 9D 5B 89 53 3A 8F B9 68 C0
+     * <p>8D EF 00 2E 75 32 5C B8 79 D1 62 80 56 ED 96 44 8F D1 00 2E 54 0C 4E 50 51 FA 53
+     * <p>E3 96 44 8F D1 00 2E 00 28 00 4E 00 32 00 32 00 2E 00 35 00 37 00 35 00 2C 00 45
+     * <p>00 31 00 31 00 33 00 2E 00 39 00 31 00 37 00 29 96 44 8F D1 26 26 00 00 00 00 00
+     * <p>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 23 00 14 87 07 0D 0A
+     */
+    private void replyLbsWarn(Channel channel) {
+        byte[] contentToReply = new byte[]{
+                (byte) 0x9A, 0x17, (byte) 0x94, 0x00, 0x00, 0x00, 0x01, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x26,
+                0x26, 0x7D, 0x27, 0x60, 0x25, 0x54, 0x7C, 0x53, (byte) 0xEB, 0x00,
+                0x3A, 0x5E, 0x7F, 0x4E, 0x1C, 0x77, 0x01, 0x00, 0x2E, 0x6D, (byte) 0xF1, 0x57, 0x33, 0x5E, 0x02, 0x00
+                , 0x2E,
+                0x5B, (byte) 0x9D, 0x5B, (byte) 0x89, 0x53, 0x3A, (byte) 0x8F, (byte) 0xB9, 0x68, (byte) 0xC0,
+                (byte) 0x8D, (byte) 0xEF, 0x00, 0x2E, 0x75, 0x32, 0x5C, (byte) 0xB8, 0x79, (byte) 0xD1, 0x62,
+                (byte) 0x80, 0x56, (byte) 0xED, (byte) 0x96, 0x44, (byte) 0x8F,
+                (byte) 0xD1, 0x00, 0x2E, 0x54, 0x0C, 0x4E, 0x50, 0x51, (byte) 0xFA, 0x53,
+                (byte) 0xE3, (byte) 0x96, 0x44, (byte) 0x8F, (byte) 0xD1, 0x00, 0x2E, 0x00, 0x28, 0x00, 0x4E, 0x00,
+                0x32, 0x00, 0x32, 0x00, 0x2E,
+                0x00, 0x35, 0x00, 0x37, 0x00, 0x35, 0x00, 0x2C, 0x00, 0x45,
+                0x00, 0x31, 0x00, 0x31, 0x00, 0x33, 0x00, 0x2E, 0x00, 0x39, 0x00, 0x31, 0x00, 0x37, 0x00, 0x29,
+                (byte) 0x96,
+                0x44, (byte) 0x8F, (byte) 0xD1, 0x26, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23,
+                0x23, 0x00, 0x14
+        };
+        writeToClient(channel, "LBS报警报", contentToReply);
+    }
 
-                // 状态: 0(失败), 1(成功)
-                byte[] signResult = new byte[]{0x01, signResponse};
-                // 0X0F是长度,固定长度
-                byte[] contentsOfPackage = mergeByteArray(new byte[]{0X0F, SIGN_IN_MSG},
-                        dataBytes, signResult, reservedWorkBytes, serNumBytes);
-                writeToClient(channel, "打卡包", contentsOfPackage);
+    private void replayForSignIn(ByteBuf in, int length, Channel channel) {
+        byte[] dataBytes = new byte[6];
+        in.readBytes(dataBytes);
 
-            } else  {
-                logger.info("client send data without handle type ...");
+        in.skipBytes(1);
+        byte[] reservedWorkBytes = new byte[2];
+        in.readBytes(reservedWorkBytes);
+
+        // 根据文档查看上下班标示
+        ByteBuf byteBuf = null;
+        byte b;
+        try {
+            byteBuf = in.readBytes(13);
+            byteBuf.skipBytes(12);
+            b = byteBuf.readByte();
+        } finally {
+            if (byteBuf != null) {
+                byteBuf.release();
             }
         }
+        // 2-5位代表是上班还是下班
+        byte i = (byte) (b & MARK);
 
+//                类型: 1(上班), 2(下班)
+        Byte signResponse = null;
+        if (i == SIGN_IN) {
+            signResponse = 0X01;
+        } else {
+            signResponse = 0x02;
+        }
+
+        // 减去前面跳过的第一位和前面跳过的7位,再减去最后的四位(序列号本身的2位+校验位2位)
+        in.skipBytes(length - 8 - 2 - 2 - 15);
+        short serNum = in.readShort();
+        byte[] serNumBytes = short2Bytes(serNum);
+
+        // 状态: 0(失败), 1(成功)
+        byte[] signResult = new byte[]{0x01, signResponse};
+        // 0X0F是长度,固定长度
+        byte[] contentsOfPackage = mergeByteArray(new byte[]{0X0F, SIGN_IN_MSG},
+                dataBytes, signResult, reservedWorkBytes, serNumBytes);
+        writeToClient(channel, "打卡包", contentsOfPackage);
     }
 
     private byte[] short2Bytes(short x) {
@@ -271,6 +369,12 @@ public class GK309GpsServerHandler extends HexBinaryAcceptanceHandlerAdapter {
         writeToClient(channel, msg, contentsOfPackage);
     }
 
+    /**
+     * 回复给客户端
+     * @param channel
+     * @param msg
+     * @param contentsOfPackage
+     */
     private void writeToClient(Channel channel, String msg, byte[] contentsOfPackage) {
         ByteBuf buffer = Unpooled.buffer();
         byte[] bytesToReply = wrapeContents(contentsOfPackage);
@@ -282,6 +386,11 @@ public class GK309GpsServerHandler extends HexBinaryAcceptanceHandlerAdapter {
         });
     }
 
+    /**
+     * 对数据做CRC校验并添加校验位/开始位置/结束位置
+     * @param contentsOfPackage 数据内容指的是去除起始位,校验位和结束位的部分: startBit + contentsOfPackage + crcBytes + endbit
+     * @return 可以直接写给客户端的数据
+     */
     private byte[] wrapeContents(byte[] contentsOfPackage) {
         int doCrc = CRCUtil.do_crc(65535, contentsOfPackage);//CRC-ITU
         byte[] crcBytes = NumUtil.intToByte(doCrc, 2);