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