diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/CRC16Util.java b/jsowell-common/src/main/java/com/jsowell/common/util/CRC16Util.java index eceb4753f..b2ef04ec0 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/CRC16Util.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/CRC16Util.java @@ -186,6 +186,20 @@ public class CRC16Util { /*以下方法得出的校验位:低位在前,高位在后*/ + public static short calculateCrc(short serialNumber, byte encryptFlag, byte frameType, byte[] messageBody) { + // short serialNumber 转byte[] + byte[] serialNumberBytes = new byte[2]; + // byte encryptFlag 转byte[] + byte[] encryptFlagBytes = new byte[1]; + // byte frameType 转byte[] + byte[] frameTypeBytes = new byte[1]; + // byte[] messageBody 转byte[] + // 序列号域+加密标志+帧类型标志+消息体 + byte[] data = Bytes.concat(serialNumberBytes, encryptFlagBytes, frameTypeBytes, messageBody); + int i = calcCrc16(data); + return (short) i; + } + /** * @param data 需要计算的数组 * @return CRC16校验值 diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YkcProtocolDecoder.java b/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YkcProtocolDecoder.java new file mode 100644 index 000000000..b34136d2f --- /dev/null +++ b/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YkcProtocolDecoder.java @@ -0,0 +1,105 @@ +package com.jsowell.netty.decoder; + +import com.jsowell.common.util.BytesUtil; +import com.jsowell.common.util.CRC16Util; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.codec.DecoderException; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +@Slf4j +public class YkcProtocolDecoder extends ByteToMessageDecoder { + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + log.info("YkcProtocolDecoder.decode"); + // 检查起始标志是否为0x68 + if (in.readableBytes() < 5) { + return; // 至少需要 起始标志 (1) + 数据长度 (1) + 序列号域 (2) + 帧校验域 (1) + } + + in.markReaderIndex(); // 标记当前读取位置 + byte startFlag = in.readByte(); + log.info("startFlag: {}", BytesUtil.binary(new byte[]{startFlag}, 16)); + if (startFlag != (byte) 0x68) { + throw new DecoderException("Invalid start flag: " + startFlag); + } + + // 读取数据长度 + byte dataLength = in.readByte(); + if (in.readableBytes() < dataLength + 2) { // 消息体 + 帧校验域长度 + in.resetReaderIndex(); + return; // 数据不足,等待更多字节 + } + + // 读取其他字段 + short serialNumber = in.readShort(); // 序列号域 + log.info("serialNumber: {}", BytesUtil.printHexBinary(new byte[]{(byte) serialNumber})); + byte encryptFlag = in.readByte(); // 加密标志 + log.info("encryptFlag: {}", BytesUtil.printHexBinary(new byte[]{encryptFlag})); + byte frameType = in.readByte(); // 帧类型标志 + log.info("frameType: {}", BytesUtil.printHexBinary(new byte[]{frameType})); + + // 读取消息体 + byte[] messageBody = new byte[dataLength - 4]; // 消息体长度 = 数据长度 - 固定字段长度 + log.info("messageBody: {}", BytesUtil.printHexBinary(messageBody)); + in.readBytes(messageBody); + + // 读取帧校验域 + short receivedCrc = in.readShort(); + + // 计算 CRC + short calculatedCrc = CRC16Util.calculateCrc(serialNumber, encryptFlag, frameType, messageBody); + if (calculatedCrc != receivedCrc) { + throw new DecoderException("CRC check failed. Expected: " + receivedCrc + ", Calculated: " + calculatedCrc); + } + + // 构造消息对象并传递给下一个处理器 + ProtocolMessage message = new ProtocolMessage(startFlag, dataLength, serialNumber, encryptFlag, frameType, messageBody, receivedCrc); + out.add(message); + } + + public static int bcdToDecimal(byte bcd1, byte bcd2) { + // BCD码转换为十进制 + int high = (bcd1 >> 4) & 0x0F; // 高4位 + int low = bcd1 & 0x0F; // 低4位 + int high2 = (bcd2 >> 4) & 0x0F; + int low2 = bcd2 & 0x0F; + + // 将BCD码拼接成十进制数 + return (high * 1000) + (low * 100) + (high2 * 10) + low2; + } + + // 自定义消息类 + public static class ProtocolMessage { + private final byte startFlag; + private final byte dataLength; + private final short serialNumber; + private final byte encryptFlag; + private final byte frameType; + private final byte[] messageBody; + private final short crc; + + public ProtocolMessage(byte startFlag, byte dataLength, short serialNumber, byte encryptFlag, byte frameType, byte[] messageBody, short crc) { + this.startFlag = startFlag; + this.dataLength = dataLength; + this.serialNumber = serialNumber; + this.encryptFlag = encryptFlag; + this.frameType = frameType; + this.messageBody = messageBody; + this.crc = crc; + } + + // Getter methods... + public byte getStartFlag() { return startFlag; } + public byte getDataLength() { return dataLength; } + public short getSerialNumber() { return serialNumber; } + public byte getEncryptFlag() { return encryptFlag; } + public byte getFrameType() { return frameType; } + public byte[] getMessageBody() { return messageBody; } + public short getCrc() { return crc; } + } +} diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YouDianDecoder.java b/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YouDianProtocolDecoder.java similarity index 96% rename from jsowell-netty/src/main/java/com/jsowell/netty/decoder/YouDianDecoder.java rename to jsowell-netty/src/main/java/com/jsowell/netty/decoder/YouDianProtocolDecoder.java index 4bea0677d..c38ebef1f 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YouDianDecoder.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YouDianProtocolDecoder.java @@ -9,13 +9,16 @@ import lombok.extern.slf4j.Slf4j; import java.nio.charset.StandardCharsets; import java.util.List; +/** + * 友电协议解码器 + */ @Slf4j -public class YouDianDecoder extends ByteToMessageDecoder { +public class YouDianProtocolDecoder extends ByteToMessageDecoder { private static final int HEADER_LENGTH_DNY = 3; // "DNY" 包头的长度 private static final int HEADER_LENGTH_68 = 1; // 68 包头的长度 // 构造函数,初始化起始标志 - public YouDianDecoder() {} + public YouDianProtocolDecoder() {} @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) throws Exception { diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YunKuaiChongDecoder.java b/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YunKuaiChongDecoder.java index cf74d6e7b..8841b1dd0 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YunKuaiChongDecoder.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/decoder/YunKuaiChongDecoder.java @@ -1,6 +1,7 @@ package com.jsowell.netty.decoder; import com.jsowell.common.constant.Constants; +import com.jsowell.common.core.domain.ykc.YKCDataProtocol; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; @@ -107,7 +108,12 @@ public class YunKuaiChongDecoder extends ByteToMessageDecoder { // 读取 data 数据 最后+2是帧校验域长度 ByteBuf frame = buffer.retainedSlice(beginReader, HEADER_LENGTH_68 + 1 + length + 2); buffer.readerIndex(beginReader + HEADER_LENGTH_68 + 1 + length + 2); - out.add(frame); + + // 转为YKCDataProtocol对象 + byte[] bytes = new byte[HEADER_LENGTH_68 + 1 + length + 2]; + frame.readBytes(bytes); + YKCDataProtocol ykcDataProtocol = new YKCDataProtocol(bytes); + out.add(ykcDataProtocol); } // 处理DNY协议消息 diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/server/electricbicycles/ElectricBicyclesServerChannelInitializer.java b/jsowell-netty/src/main/java/com/jsowell/netty/server/electricbicycles/ElectricBicyclesServerChannelInitializer.java index c58d70bd5..3b9ef4631 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/server/electricbicycles/ElectricBicyclesServerChannelInitializer.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/server/electricbicycles/ElectricBicyclesServerChannelInitializer.java @@ -1,6 +1,6 @@ package com.jsowell.netty.server.electricbicycles; -import com.jsowell.netty.decoder.YouDianDecoder; +import com.jsowell.netty.decoder.YouDianProtocolDecoder; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; @@ -20,7 +20,7 @@ public class ElectricBicyclesServerChannelInitializer extends ChannelInitializer @Override protected void initChannel(SocketChannel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); - pipeline.addLast("frameDecoder", new YouDianDecoder()); + pipeline.addLast("frameDecoder", new YouDianProtocolDecoder()); // pipeline.addLast("decoder", new MessageDecode()); // pipeline.addLast("encoder", new MessageEncode()); pipeline.addLast("decoder", new ByteArrayDecoder()); diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/server/yunkuaichong/NettyServerChannelInitializer.java b/jsowell-netty/src/main/java/com/jsowell/netty/server/yunkuaichong/NettyServerChannelInitializer.java index c2237067a..0d0184f16 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/server/yunkuaichong/NettyServerChannelInitializer.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/server/yunkuaichong/NettyServerChannelInitializer.java @@ -20,8 +20,8 @@ public class NettyServerChannelInitializer extends ChannelInitializer