|  | @@ -0,0 +1,146 @@
 | 
											
												
													
														|  | 
 |  | +package com.genersoft.iot.vmp.jt1078.codec.decode;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +import com.genersoft.iot.vmp.jt1078.proc.Header;
 | 
											
												
													
														|  | 
 |  | +import com.genersoft.iot.vmp.jt1078.proc.factory.CodecFactory;
 | 
											
												
													
														|  | 
 |  | +import com.genersoft.iot.vmp.jt1078.proc.request.Re;
 | 
											
												
													
														|  | 
 |  | +import com.genersoft.iot.vmp.jt1078.proc.response.Rs;
 | 
											
												
													
														|  | 
 |  | +import com.genersoft.iot.vmp.jt1078.session.Session;
 | 
											
												
													
														|  | 
 |  | +import io.netty.buffer.ByteBuf;
 | 
											
												
													
														|  | 
 |  | +import io.netty.buffer.ByteBufUtil;
 | 
											
												
													
														|  | 
 |  | +import io.netty.buffer.CompositeByteBuf;
 | 
											
												
													
														|  | 
 |  | +import io.netty.buffer.UnpooledByteBufAllocator;
 | 
											
												
													
														|  | 
 |  | +import io.netty.channel.ChannelHandlerContext;
 | 
											
												
													
														|  | 
 |  | +import io.netty.handler.codec.ByteToMessageDecoder;
 | 
											
												
													
														|  | 
 |  | +import org.slf4j.Logger;
 | 
											
												
													
														|  | 
 |  | +import org.slf4j.LoggerFactory;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +import java.util.ArrayList;
 | 
											
												
													
														|  | 
 |  | +import java.util.List;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +/**
 | 
											
												
													
														|  | 
 |  | + * @author QingtaiJiang
 | 
											
												
													
														|  | 
 |  | + * @date 2023/4/27 18:10
 | 
											
												
													
														|  | 
 |  | + * @email qingtaij@163.com
 | 
											
												
													
														|  | 
 |  | + */
 | 
											
												
													
														|  | 
 |  | +public class Jt808Decoder extends ByteToMessageDecoder {
 | 
											
												
													
														|  | 
 |  | +    private final static Logger log = LoggerFactory.getLogger(Jt808Decoder.class);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    @Override
 | 
											
												
													
														|  | 
 |  | +    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
 | 
											
												
													
														|  | 
 |  | +        Session session = ctx.channel().attr(Session.KEY).get();
 | 
											
												
													
														|  | 
 |  | +        log.info("> {} hex:{}", session, ByteBufUtil.hexDump(in));
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        try {
 | 
											
												
													
														|  | 
 |  | +            ByteBuf buf = unEscapeAndCheck(in);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            Header header = new Header();
 | 
											
												
													
														|  | 
 |  | +            header.setMsgId(ByteBufUtil.hexDump(buf.readSlice(2)));
 | 
											
												
													
														|  | 
 |  | +            header.setMsgPro(buf.readUnsignedShort());
 | 
											
												
													
														|  | 
 |  | +            if (header.is2019Version()) {
 | 
											
												
													
														|  | 
 |  | +                header.setVersion(buf.readUnsignedByte());
 | 
											
												
													
														|  | 
 |  | +                String devId = ByteBufUtil.hexDump(buf.readSlice(10));
 | 
											
												
													
														|  | 
 |  | +                header.setDevId(devId.replaceFirst("^0*", ""));
 | 
											
												
													
														|  | 
 |  | +            } else {
 | 
											
												
													
														|  | 
 |  | +                header.setDevId(ByteBufUtil.hexDump(buf.readSlice(6)).replaceFirst("^0*", ""));
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            header.setSn(buf.readUnsignedShort());
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            Re handler = CodecFactory.getHandler(header.getMsgId());
 | 
											
												
													
														|  | 
 |  | +            if (handler == null) {
 | 
											
												
													
														|  | 
 |  | +                log.error("get msgId is null {}", header.getMsgId());
 | 
											
												
													
														|  | 
 |  | +                return;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            Rs decode = handler.decode(buf, header, session);
 | 
											
												
													
														|  | 
 |  | +            if (decode != null) {
 | 
											
												
													
														|  | 
 |  | +                out.add(decode);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +        } finally {
 | 
											
												
													
														|  | 
 |  | +            in.skipBytes(in.readableBytes());
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    /**
 | 
											
												
													
														|  | 
 |  | +     * 转义与验证校验码
 | 
											
												
													
														|  | 
 |  | +     *
 | 
											
												
													
														|  | 
 |  | +     * @param byteBuf 转义Buf
 | 
											
												
													
														|  | 
 |  | +     * @return 转义好的数据
 | 
											
												
													
														|  | 
 |  | +     */
 | 
											
												
													
														|  | 
 |  | +    public ByteBuf unEscapeAndCheck(ByteBuf byteBuf) throws Exception {
 | 
											
												
													
														|  | 
 |  | +        int low = byteBuf.readerIndex();
 | 
											
												
													
														|  | 
 |  | +        int high = byteBuf.writerIndex();
 | 
											
												
													
														|  | 
 |  | +        byte checkSum = 0;
 | 
											
												
													
														|  | 
 |  | +        int calculationCheckSum = 0;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        byte aByte = byteBuf.getByte(high - 2);
 | 
											
												
													
														|  | 
 |  | +        byte protocolEscapeFlag7d = 0x7d;
 | 
											
												
													
														|  | 
 |  | +        //0x7d转义
 | 
											
												
													
														|  | 
 |  | +        byte protocolEscapeFlag01 = 0x01;
 | 
											
												
													
														|  | 
 |  | +        //0x7e转义
 | 
											
												
													
														|  | 
 |  | +        byte protocolEscapeFlag02 = 0x02;
 | 
											
												
													
														|  | 
 |  | +        if (aByte == protocolEscapeFlag7d) {
 | 
											
												
													
														|  | 
 |  | +            byte b2 = byteBuf.getByte(high - 1);
 | 
											
												
													
														|  | 
 |  | +            if (b2 == protocolEscapeFlag01) {
 | 
											
												
													
														|  | 
 |  | +                checkSum = protocolEscapeFlag7d;
 | 
											
												
													
														|  | 
 |  | +            } else if (b2 == protocolEscapeFlag02) {
 | 
											
												
													
														|  | 
 |  | +                checkSum = 0x7e;
 | 
											
												
													
														|  | 
 |  | +            } else {
 | 
											
												
													
														|  | 
 |  | +                log.error("转义1异常:{}", ByteBufUtil.hexDump(byteBuf));
 | 
											
												
													
														|  | 
 |  | +                throw new Exception("转义错误");
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            high = high - 2;
 | 
											
												
													
														|  | 
 |  | +        } else {
 | 
											
												
													
														|  | 
 |  | +            high = high - 1;
 | 
											
												
													
														|  | 
 |  | +            checkSum = byteBuf.getByte(high);
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +        List<ByteBuf> bufList = new ArrayList<>();
 | 
											
												
													
														|  | 
 |  | +        int index = low;
 | 
											
												
													
														|  | 
 |  | +        while (index < high) {
 | 
											
												
													
														|  | 
 |  | +            byte b = byteBuf.getByte(index);
 | 
											
												
													
														|  | 
 |  | +            if (b == protocolEscapeFlag7d) {
 | 
											
												
													
														|  | 
 |  | +                byte c = byteBuf.getByte(index + 1);
 | 
											
												
													
														|  | 
 |  | +                if (c == protocolEscapeFlag01) {
 | 
											
												
													
														|  | 
 |  | +                    ByteBuf slice = slice0x01(byteBuf, low, index);
 | 
											
												
													
														|  | 
 |  | +                    bufList.add(slice);
 | 
											
												
													
														|  | 
 |  | +                    b = protocolEscapeFlag7d;
 | 
											
												
													
														|  | 
 |  | +                } else if (c == protocolEscapeFlag02) {
 | 
											
												
													
														|  | 
 |  | +                    ByteBuf slice = slice0x02(byteBuf, low, index);
 | 
											
												
													
														|  | 
 |  | +                    bufList.add(slice);
 | 
											
												
													
														|  | 
 |  | +                    b = 0x7e;
 | 
											
												
													
														|  | 
 |  | +                } else {
 | 
											
												
													
														|  | 
 |  | +                    log.error("转义2异常:{}", ByteBufUtil.hexDump(byteBuf));
 | 
											
												
													
														|  | 
 |  | +                    throw new Exception("转义错误");
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +                index += 2;
 | 
											
												
													
														|  | 
 |  | +                low = index;
 | 
											
												
													
														|  | 
 |  | +            } else {
 | 
											
												
													
														|  | 
 |  | +                index += 1;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +            calculationCheckSum = calculationCheckSum ^ b;
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        if (calculationCheckSum == checkSum) {
 | 
											
												
													
														|  | 
 |  | +            if (bufList.size() == 0) {
 | 
											
												
													
														|  | 
 |  | +                return byteBuf.slice(low, high);
 | 
											
												
													
														|  | 
 |  | +            } else {
 | 
											
												
													
														|  | 
 |  | +                bufList.add(byteBuf.slice(low, high - low));
 | 
											
												
													
														|  | 
 |  | +                return new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, false, bufList.size(), bufList);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +        } else {
 | 
											
												
													
														|  | 
 |  | +            log.info("{} 解析校验码:{}--计算校验码:{}", ByteBufUtil.hexDump(byteBuf), checkSum, calculationCheckSum);
 | 
											
												
													
														|  | 
 |  | +            throw new Exception("校验码错误!");
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    private ByteBuf slice0x01(ByteBuf buf, int low, int sign) {
 | 
											
												
													
														|  | 
 |  | +        return buf.slice(low, sign - low + 1);
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    private ByteBuf slice0x02(ByteBuf buf, int low, int sign) {
 | 
											
												
													
														|  | 
 |  | +        buf.setByte(sign, 0x7e);
 | 
											
												
													
														|  | 
 |  | +        return buf.slice(low, sign - low + 1);
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +}
 |