|
|
@@ -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);
|
|
|
+ }
|
|
|
+}
|