From 1560f3063ca90d41c0717f8ed6e1fb00fde64776 Mon Sep 17 00:00:00 2001 From: luxiaotao1123 <t1341870251@163.com> Date: 星期一, 12 八月 2024 15:56:56 +0800 Subject: [PATCH] # --- app/src/main/java/com/example/agvcontroller/protocol/PacHeader.java | 98 ++++++++++ app/src/main/java/com/example/agvcontroller/protocol/AGV_02_DOWN.java | 47 +++++ app/src/main/java/com/example/agvcontroller/protocol/AgvPackage.java | 157 +++++++++++++++++ app/src/main/java/com/example/agvcontroller/protocol/ProtocolEncoder.java | 89 +++++++++ app/src/main/java/com/example/agvcontroller/protocol/CRCUtils.java | 41 ++++ app/src/main/java/com/example/agvcontroller/protocol/ProtocolUtils.java | 86 +++++++++ app/src/main/java/com/example/agvcontroller/protocol/IMessageBody.java | 11 + 7 files changed, 529 insertions(+), 0 deletions(-) diff --git a/app/src/main/java/com/example/agvcontroller/protocol/AGV_02_DOWN.java b/app/src/main/java/com/example/agvcontroller/protocol/AGV_02_DOWN.java new file mode 100644 index 0000000..74bde9d --- /dev/null +++ b/app/src/main/java/com/example/agvcontroller/protocol/AGV_02_DOWN.java @@ -0,0 +1,47 @@ +package com.zy.acs.common.domain.protocol; + +import com.zy.acs.common.utils.Utils; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; + +/** + * 鍔ㄤ綔鍛戒护鍖� + * Created by vincent on 2023/3/21 + */ +@Data +public class AGV_02_DOWN implements IMessageBody, Serializable { + + private static final long serialVersionUID = 1664188062202647371L; + + @Override + public byte[] writeToBytes() { + String serialNo = Utils.zeroFill(this.serialNo, 16); + byte[] serialNoBytes = Utils.reverse(serialNo.getBytes()); + byte cmdCodeByte = (byte) this.getCmdCode(); + byte valByte = (byte) this.getVal(); + + byte[] cmdBodyBytes = commandBody.writeToBytes(); + + return Utils.merge(serialNoBytes, cmdCodeByte, valByte, cmdBodyBytes); + } + + @Override + public void readFromBytes(byte[] messageBodyBytes) { + + } + + // 娴佹按鍙� - 16 + private String serialNo; + + // 鍛戒护鐮� + private int cmdCode; + + // 灞炴�у�� + private int val; + + // 鍔ㄤ綔鍙傛暟 + private ICommandBody commandBody; + +} diff --git a/app/src/main/java/com/example/agvcontroller/protocol/AgvPackage.java b/app/src/main/java/com/example/agvcontroller/protocol/AgvPackage.java new file mode 100644 index 0000000..e50fa82 --- /dev/null +++ b/app/src/main/java/com/example/agvcontroller/protocol/AgvPackage.java @@ -0,0 +1,157 @@ +package com.zy.acs.gateway.domain; + +import com.core.common.Cools; +import com.zy.acs.gateway.constant.AgvConstant; +import com.zy.acs.gateway.constant.PacErrorType; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +import java.util.Objects; + +/** + * AGV鎶ユ枃妯″瀷 + * Created by vincent on 2023/3/10 + */ +public class AgvPackage implements PackageSupport { + + /** + * 婧愭暟鎹寘缂撳啿鍖�(寮曠敤) + */ + private ByteBuf sourceBuff; + + /** + * 鍘熷娑堟伅瀵瑰簲鐨�16杩涘埗瀛楃涓� + */ + private String sourceHexStr; + + /** + * 娑堟伅澶撮儴 + */ + private PacHeader header; + + /** + * 娑堟伅浣� + */ + private PacBody body; + + /** + * 娑堟伅鐨勬牎姝g爜 + */ + private int validCode; + + /** + * 鏄惁涓烘牎楠屽紓甯稿寘 + */ + private boolean errorPac; + + /** + * 鏍¢獙寮傚父绫诲瀷 + */ + private PacErrorType pacErrorType; + + public static AgvPackage valueOfEmpty() { + AgvPackage agvPackage = new AgvPackage(); + agvPackage.setHeader(new PacHeader()) + .setBody(new PacBody()) + .setValidCode((short) 0) + .setErrorPac(false); + return agvPackage; + } + + public String toLogString() { + StringBuilder pacSb = new StringBuilder(); + pacSb.append("AGV(").append(getHeader().getUniqueNo()).append(")") + .append("涓婁紶") + .append("[").append(getHeader().getProtocolType().getDes()).append("]娑堟伅.") + .append("鍘熷娑堟伅[").append(getSourceHexStr()).append("]"); + return pacSb.toString(); + } + + public ByteBuf getSourceBuff() { + // 鍥犱负澶勭悊buffer鏃讹紝鎬绘槸甯屾湜鎷垮埌涓�涓噸缃簡readerIndex鐨刡uf + if (Objects.nonNull(this.sourceBuff)) { + this.sourceBuff.resetReaderIndex(); + } + return this.sourceBuff; + } + + public AgvPackage setSourceBuff(ByteBuf sourceBuff) { + this.sourceBuff = sourceBuff; + if (Cools.isEmpty(this.sourceHexStr)) { + this.sourceBuff.resetReaderIndex(); + this.sourceHexStr = ByteBufUtil.hexDump(this.sourceBuff).toUpperCase(); + this.sourceBuff.resetReaderIndex(); + } + return this; + } + + public PacHeader getHeader() { + return header; + } + + public AgvPackage setHeader(PacHeader header) { + this.header = header; + return this; + } + + public PacBody getBody() { + return body; + } + + public AgvPackage setBody(PacBody body) { + this.body = body; + return this; + } + + public int getValidCode() { + return validCode; + } + + public AgvPackage setValidCode(int validCode) { + this.validCode = validCode; + return this; + } + + public boolean isErrorPac() { + return errorPac; + } + + public AgvPackage setErrorPac(boolean errorPac) { + this.errorPac = errorPac; + return this; + } + + public String getSourceHexStr() { + return sourceHexStr; + } + + public AgvPackage setSourceHexStr(String sourceHexStr) { + this.sourceHexStr = sourceHexStr; + return this; + } + + public PacErrorType getPacErrorType() { + return pacErrorType; + } + + public AgvPackage setPacErrorType(PacErrorType pacErrorType) { + this.pacErrorType = pacErrorType; + return this; + } + + public ByteBuf convert(ByteBuf byteBuf){ + byteBuf.writeByte(this.getHeader().getStartSymbol()) + .writeShort(this.getHeader().getContentLength()) + .writeByte(this.getHeader().getProtocolType().getCode()) + .writeBytes(this.getHeader().getUniqueNo().getBytes(AgvConstant.CHARSET_GBK)) + .writeByte(this.getHeader().getEncryptType().getCode()) + .writeBytes(this.getBody().getContent()) + .writeByte(this.getValidCode()); + // 璁$畻骞惰缃牎楠岀爜 +// this.setValidCode(ValidUtil.caculateValidByteFromBuff(byteBuf)); + byteBuf.resetReaderIndex(); + byteBuf.writerIndex(byteBuf.readableBytes() - 1).writeByte(this.getValidCode()); + return byteBuf; + } + +} diff --git a/app/src/main/java/com/example/agvcontroller/protocol/CRCUtils.java b/app/src/main/java/com/example/agvcontroller/protocol/CRCUtils.java new file mode 100644 index 0000000..a5047c8 --- /dev/null +++ b/app/src/main/java/com/example/agvcontroller/protocol/CRCUtils.java @@ -0,0 +1,41 @@ +package com.zy.acs.gateway.utils; + +/** + * CRC16寰幆鍐椾綑鏍¢獙鐮� + * Created by vincent on 2023/3/13 + */ +public class CRCUtils { + + /** + * 涓�涓瓧鑺傚崰 8浣� + */ + private static final int BITS_OF_BYTE = 8; + + /** + * 澶氶」寮� + */ + private static final int POLYNOMIAL = 0XA001; + + /** + * CRC瀵勫瓨鍣ㄩ粯璁ゅ垵濮嬪�� + */ + private static final int INITIAL_VALUE = 0XFFFF; + + /** + * CRC16 缂栫爜 + * @param bytes 缂栫爜鍐呭 + * @return 缂栫爜缁撴灉 + */ + public static int crc16(byte[] bytes) { + int res = INITIAL_VALUE; + for (byte data : bytes) { + // 鎶奲yte杞崲鎴恑nt鍚庡啀璁$畻 + res = res ^ (data & 0XFF); + for (int i = 0; i < BITS_OF_BYTE; i++) { + res = (res & 0X0001) == 1 ? (res >> 1) ^ POLYNOMIAL : res >> 1; + } + } + return res; + } + +} diff --git a/app/src/main/java/com/example/agvcontroller/protocol/IMessageBody.java b/app/src/main/java/com/example/agvcontroller/protocol/IMessageBody.java new file mode 100644 index 0000000..a6a6d90 --- /dev/null +++ b/app/src/main/java/com/example/agvcontroller/protocol/IMessageBody.java @@ -0,0 +1,11 @@ +package com.zy.acs.common.domain.protocol; + +import java.io.Serializable; + +public interface IMessageBody extends Serializable { + + byte[] writeToBytes(); + + void readFromBytes(byte[] messageBodyBytes); + +} diff --git a/app/src/main/java/com/example/agvcontroller/protocol/PacHeader.java b/app/src/main/java/com/example/agvcontroller/protocol/PacHeader.java new file mode 100644 index 0000000..a41be16 --- /dev/null +++ b/app/src/main/java/com/example/agvcontroller/protocol/PacHeader.java @@ -0,0 +1,98 @@ +package com.zy.acs.gateway.domain; + +import com.zy.acs.gateway.constant.EncryType; +import com.zy.acs.gateway.constant.ProtocolType; +import lombok.Data; +import org.apache.commons.lang.builder.ToStringBuilder; + +/** + * 鍗忚澶� + * Created by vincent on 2019-04-03 + */ +@Data +public class PacHeader { + + /** + * 璧峰绗� + * 鍥哄畾涓�"0xEE || 0xAA" + */ + private byte startSymbol; + + /** + * 鏁版嵁鍗曞厓闀垮害 + */ + private int contentLength; + + /** + * 鍞竴鏍囪瘑鐮� + */ + private String uniqueNo; + + /** + * 鏃堕棿鎴� + */ + private int timestamp; + + /** + * 鍛戒护鏍囪瘑 + */ + private ProtocolType protocolType; + + /** + * 娴佹按鍙� + */ + private String serialNum; + + /** + * 鏁版嵁鍗曞厓鍔犲瘑鏂瑰紡 + */ + private EncryType encryptType; + + + public PacHeader setStartSymbol(Byte startSymbol) { + this.startSymbol = startSymbol; + return this; + } + + public PacHeader setProtocolType(ProtocolType protocolType) { + this.protocolType = protocolType; + return this; + } + + public PacHeader setTimestamp(Integer timestamp) { + this.timestamp = timestamp; + return this; + } + + public PacHeader setSerialNum(String serialNum) { + this.serialNum = serialNum; + return this; + } + + public PacHeader setUniqueNo(String uniqueNo) { + this.uniqueNo = uniqueNo; + return this; + } + + public PacHeader setEncryptType(EncryType encryptType) { + this.encryptType = encryptType; + return this; + } + + public PacHeader setContentLength(int contentLength) { + this.contentLength = contentLength; + return this; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("startSymbol", startSymbol) + .append("contentLength", contentLength) + .append("uniqueNo", uniqueNo) + .append("timestamp", timestamp) + .append("protocolType", protocolType.getDes()) + .append("serialNum", serialNum) + .toString(); + } +} diff --git a/app/src/main/java/com/example/agvcontroller/protocol/ProtocolEncoder.java b/app/src/main/java/com/example/agvcontroller/protocol/ProtocolEncoder.java new file mode 100644 index 0000000..04a396a --- /dev/null +++ b/app/src/main/java/com/example/agvcontroller/protocol/ProtocolEncoder.java @@ -0,0 +1,89 @@ +package com.zy.acs.gateway.handler.coder; + +import com.core.common.RadixTools; +import com.zy.acs.common.utils.Utils; +import com.zy.acs.gateway.config.SystemProperties; +import com.zy.acs.gateway.constant.PackagePart; +import com.zy.acs.gateway.domain.AgvPackage; +import com.zy.acs.gateway.utils.ValidUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 缂栫爜鍣� + * 姝よВ鐮佸櫒灏嗕細鐢熸垚鏍¢獙鐮� + * 澶勭悊鏂瑰紡: 寮傛垨鍜� + * Created by vincent on 2019-04-02 + */ +@Component +@ChannelHandler.Sharable +public class ProtocolEncoder extends MessageToByteEncoder<Object> { + + private static final Logger log = LoggerFactory.getLogger(ProtocolEncoder.class); + + @Autowired + private SystemProperties systemProperties; + + @Override + protected void encode(ChannelHandlerContext ctx, Object obj, ByteBuf out) { + + if (obj instanceof ByteBuf){ + out.writeBytes((ByteBuf) obj); + + } else if (obj instanceof byte[]){ + out.writeBytes((byte[]) obj); + + } else if (obj instanceof AgvPackage){ + + AgvPackage pac = (AgvPackage)obj; + + + + byte[] bodyBytes = pac.getBody().getMessageBody().writeToBytes(); // body + + String uniqueNo = pac.getHeader().getUniqueNo(); + + byte[] uniquenoBytes = RadixTools.intToBytes(Integer.parseInt(pac.getHeader().getUniqueNo())); // uniqueno + + + int len = PackagePart.UNIQUENO.getLen() // len + + PackagePart.TIMESTAMP.getLen() + + PackagePart.COMMAND_MARK.getLen() + + bodyBytes.length; + + out.writeByte(pac.getHeader().getStartSymbol()) // symbol + .writeShortLE(len) + .writeBytes(Utils.reverse(uniquenoBytes)) // uniqueno + .writeIntLE((int) (System.currentTimeMillis() / 1000)) // timestamp + .writeByte(pac.getHeader().getProtocolType().getCode()) // type + .writeBytes(bodyBytes) // body + .writeShort(pac.getValidCode()) // valid + ; + + pac.setValidCode(ValidUtil.calculateValidByteFromBuff(out)); + out.resetReaderIndex(); + + out.writerIndex(out.readableBytes() - 2); + out.writeShortLE(pac.getValidCode()); + + + if (systemProperties.isPrintPacLog()){ + log.info("Agv [{}] 涓嬭 [{}] >>> {}", uniqueNo, pac.getHeader().getProtocolType().getDes(), ByteBufUtil.hexDump(out).toUpperCase()); + } + + } + + + } + +// EE | 11 00 | 01 00 00 00 | 0C AB 12 64 | F0 | 01 00 | 01 01 | 00 00 00 00 | 4C F7 +// # | len | uniqueno | timestamp | cmd | content | crc + +} diff --git a/app/src/main/java/com/example/agvcontroller/protocol/ProtocolUtils.java b/app/src/main/java/com/example/agvcontroller/protocol/ProtocolUtils.java new file mode 100644 index 0000000..2ea178b --- /dev/null +++ b/app/src/main/java/com/example/agvcontroller/protocol/ProtocolUtils.java @@ -0,0 +1,86 @@ +package com.zy.acs.gateway.utils; + +import com.zy.acs.common.domain.AgvProtocol; +import com.zy.acs.common.domain.protocol.IMessageBody; +import com.zy.acs.gateway.constant.ProtocolPojoType; +import com.zy.acs.gateway.constant.ProtocolType; +import com.zy.acs.gateway.domain.AgvPackage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by vincent on 2019-04-03 + */ +public class ProtocolUtils { + + private static final Logger log = LoggerFactory.getLogger(ProtocolUtils.class); + + // 涓嬭鍗忚鎶ユ枃缁勮 + public static AgvPackage installDownProtocol(AgvProtocol protocol){ + + + ProtocolPojoType protocolPojo = ProtocolPojoType.query(protocol.getMessageBody().getClass()); + + assert protocolPojo != null; + + AgvPackage ackPackage = AgvPackage.valueOfEmpty(); + ackPackage.getHeader() + .setStartSymbol((byte)0xEE) + .setContentLength(0) + .setUniqueNo(protocol.getAgvNo()) + .setTimestamp(protocol.getTimestamp()) + .setProtocolType(protocolPojo.protocolType) + ; + + ackPackage.getBody().setMessageBody(protocol.getMessageBody()); + + return ackPackage; + + } + + // 涓嬭鍗忚鎶ユ枃缁勮 + public static AgvPackage installDownProtocol(String uniqueNo, ProtocolType protocolType){ + + + AgvPackage ackPackage = AgvPackage.valueOfEmpty(); + ackPackage.getHeader() + .setStartSymbol((byte)0xEE) + .setContentLength(0) + .setUniqueNo(uniqueNo) + .setTimestamp((int)System.currentTimeMillis()/1000) + .setProtocolType(protocolType) + ; + + ProtocolPojoType protocolPojo = ProtocolPojoType.query(protocolType); + + + assert protocolPojo != null; + + + IMessageBody iMessageBody = null; + + try { + + iMessageBody = protocolPojo.clazz.newInstance(); + } catch (ReflectiveOperationException reflectiveOperationException) { + + + log.error("MessageBodyHandler ReflectiveOperationException", reflectiveOperationException); + + log.error("java鍙嶅皠鍒涘缓瀹炰緥澶辫触锛歿}", protocolPojo.clazz.getName()); + + return null; + } + + + + ackPackage.getBody().setMessageBody(iMessageBody); + + + + return ackPackage; + } + + + +} -- Gitblit v1.9.1