From dbeb3dd2e88d28da73ebc1f6843355fb51e5603f Mon Sep 17 00:00:00 2001 From: whycq <913841844@qq.com> Date: 星期五, 16 八月 2024 08:50:00 +0800 Subject: [PATCH] # --- .idea/deploymentTargetSelector.xml | 8 + app/src/main/java/com/example/agvcontroller/StartActivity.java | 2 app/src/main/res/layout/activity_main.xml | 96 ++++++++++++++++++ app/src/main/java/com/example/agvcontroller/socket/NettyServer.java | 2 app/src/main/java/com/example/agvcontroller/protocol/ProtocolDecoder.java | 158 +++++++++++++++++++++++++++++++ 5 files changed, 263 insertions(+), 3 deletions(-) diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index b268ef3..32ed794 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -4,6 +4,14 @@ <selectionStates> <SelectionState runConfigName="app"> <option name="selectionMode" value="DROPDOWN" /> + <DropdownSelection timestamp="2024-08-15T08:33:10.282255800Z"> + <Target type="DEFAULT_BOOT"> + <handle> + <DeviceId pluginId="PhysicalDevice" identifier="serial=2MM0223916052360" /> + </handle> + </Target> + </DropdownSelection> + <DialogSelection /> </SelectionState> </selectionStates> </component> diff --git a/app/src/main/java/com/example/agvcontroller/StartActivity.java b/app/src/main/java/com/example/agvcontroller/StartActivity.java index adb74d2..f38311e 100644 --- a/app/src/main/java/com/example/agvcontroller/StartActivity.java +++ b/app/src/main/java/com/example/agvcontroller/StartActivity.java @@ -52,7 +52,7 @@ } }); socketManager = new SocketManager(); - socketManager.startServer(8022); + socketManager.startServer(8080); } @Subscribe(threadMode = ThreadMode.MAIN) diff --git a/app/src/main/java/com/example/agvcontroller/protocol/ProtocolDecoder.java b/app/src/main/java/com/example/agvcontroller/protocol/ProtocolDecoder.java new file mode 100644 index 0000000..b710520 --- /dev/null +++ b/app/src/main/java/com/example/agvcontroller/protocol/ProtocolDecoder.java @@ -0,0 +1,158 @@ +package com.example.agvcontroller.protocol; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.util.ReferenceCountUtil; +import com.example.agvcontroller.socket.RadixTools; + +import java.net.InetSocketAddress; +import java.util.List; + +/** + * Created by vincent on 2019-04-10 + */ +public class ProtocolDecoder extends ByteToMessageDecoder { + + private final int maxFrameLength; + + public ProtocolDecoder(int maxFrameLength){ + this.maxFrameLength = maxFrameLength; + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { + String ip = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress(); +// log.info("ip:{} ===>> {}", ip, ByteBufUtil.hexDump(in).toUpperCase()); + + int startMark = indexOfStartMark(in); + if (startMark == -1){ + in.skipBytes(in.readableBytes()); + return; + } + if (in.readableBytes() > maxFrameLength) { + in.skipBytes(in.readableBytes()); + return; + } + // 鍘婚櫎鏃犵敤鍓嶇紑鎶ユ枃 + if (startMark != 0){ + in.readerIndex(startMark); + in.discardReadBytes(); + } + // 绮樺寘澶勭悊 + in.markReaderIndex(); + in.readerIndex(PackagePart.CONTENT_LENGTH.getStartIndex()); + int pacTotalLen = PackagePart.START_SYMBOL.getLen() + + PackagePart.CONTENT_LENGTH.getLen() + + in.readShortLE() + + PackagePart.VALIDE_CODE.getLen() + ; + in.resetReaderIndex(); + ByteBuf byteBuf = in.readSlice(pacTotalLen); + + // 鐢熸垚鍜屽垵濮嬪寲娑堟伅鍖呰绫� + AgvPackage pac = AgvPackage.valueOfEmpty(); + pac.setSourceBuff(byteBuf); + // 瑙f瀽 + out.add(analyzeProtocol(pac)); + + // byteBuf.resetReaderIndex(); // tip: 濡傛灉 ridx == widx锛屽垯 refCnt = 0 + in.resetReaderIndex(); + in.skipBytes(pacTotalLen); // tip: This method will be called till either the input has nothing to read锛屾棤璇紒 + + ReferenceCountUtil.retain(in); // 瑙g爜鍣ㄨ嚜鍔ㄩ噴鏀� refCnt - 1 + + } + + public AgvPackage analyzeProtocol(AgvPackage pac){ + ByteBuf byteBuf = pac.getSourceBuff(); + PacHeader pacHeader = pac.getHeader(); + // 鍞竴鏍囪瘑鐮� + byteBuf.readerIndex(PackagePart.UNIQUENO.getStartIndex()); + byte[] bytes = new byte[PackagePart.UNIQUENO.getLen()]; + byteBuf.readBytes(bytes); + Utils.reverse(bytes); + String uniqueno = String.valueOf(RadixTools.bytesToInt(bytes)); + if (!Cools.isEmpty(uniqueno)) { + pacHeader.setUniqueNo(uniqueno); + byteBuf.resetReaderIndex(); + } else { + return pac.setErrorPac(Boolean.TRUE).setPacErrorType(PacErrorType.PAC_ANALYZE_ERROR); + } + // 鑾峰彇鏍囪瘑绗� + byte startSymbol = byteBuf.readByte(); + DirectionType direction = null; + if ((0xEE&0xFF) == (startSymbol&0xFF)) { + pacHeader.setStartSymbol(startSymbol); + direction = DirectionType.DOWN; + } else if ((0xAA&0xFF) == (startSymbol&0xFF)) { + pacHeader.setStartSymbol(startSymbol); + direction = DirectionType.UP; + } else { + return pac.setErrorPac(Boolean.TRUE).setPacErrorType(PacErrorType.PAC_ANALYZE_ERROR); + } + // 鑾峰彇鍗忚浣撻暱搴� + int contentLength = byteBuf.readShortLE(); + if (contentLength >= 0) { + pacHeader.setContentLength(contentLength); + } else { + return pac.setErrorPac(Boolean.TRUE).setPacErrorType(PacErrorType.PAC_ANALYZE_ERROR); + } + // skip uniqueNo + byteBuf.readerIndex(byteBuf.readerIndex() + PackagePart.UNIQUENO.getLen()); + // 鑾峰彇鏃堕棿鎴� + byteBuf.readerIndex(PackagePart.TIMESTAMP.getStartIndex()); + int timestamp = byteBuf.readIntLE(); + if (timestamp > 0) { + pacHeader.setTimestamp(timestamp); + } else { + return pac.setErrorPac(Boolean.TRUE).setPacErrorType(PacErrorType.PAC_ANALYZE_ERROR); + } + // 鑾峰彇鍛戒护鏍囪瘑 + int commandByte = byteBuf.readByte() & 0xFF; + ProtocolType protocolType = ProtocolType.getByCode(commandByte, direction); + if (null != protocolType) { + pacHeader.setProtocolType(protocolType); + } else { + return pac.setErrorPac(Boolean.TRUE).setPacErrorType(PacErrorType.PAC_ANALYZE_ERROR); + } + // 鑾峰彇鍗忚浣� + if (contentLength > 0) { + ByteBuf body = byteBuf.readSlice(pac.getHeader().getContentLength() - ( + + PackagePart.UNIQUENO.getLen() + + PackagePart.TIMESTAMP.getLen() + + PackagePart.COMMAND_MARK.getLen() + )); + if (null != body && body.readableBytes() >= 0) { + pac.getBody().setContent(body); + } else { + return pac.setErrorPac(Boolean.TRUE).setPacErrorType(PacErrorType.PAC_ANALYZE_ERROR); + } + } + // 鏍¢獙鐮� + if(byteBuf.readableBytes() == 2) { + pac.setValidCode(byteBuf.readUnsignedShortLE()); + } else { + return pac.setErrorPac(Boolean.TRUE).setPacErrorType(PacErrorType.PAC_ANALYZE_ERROR); + } + return pac; + } + + // 鑾峰彇鏍囪瘑浣嶄笅鏍� + private int indexOfStartMark(ByteBuf inputBuffer){ + int length = inputBuffer.writerIndex(); + // 鎶ユ枃闀垮害鑷冲皯澶т簬2 + if (length < 2) { + return -1; + } + int readerIndex = inputBuffer.readerIndex(); + for(int i = readerIndex; i < length - 1; i ++) { + byte b1 = inputBuffer.getByte(i); + if ((0xEE&0xFF) == (b1&0xFF) || (0xAA&0xFF) == (b1&0xFF)) { + return i; + } + } + return -1; + } + +} diff --git a/app/src/main/java/com/example/agvcontroller/socket/NettyServer.java b/app/src/main/java/com/example/agvcontroller/socket/NettyServer.java index 06bd508..1f91141 100644 --- a/app/src/main/java/com/example/agvcontroller/socket/NettyServer.java +++ b/app/src/main/java/com/example/agvcontroller/socket/NettyServer.java @@ -1,5 +1,6 @@ package com.example.agvcontroller.socket; +import com.example.agvcontroller.protocol.ProtocolDecoder; import com.example.agvcontroller.protocol.ProtocolEncoder; import io.netty.bootstrap.ServerBootstrap; @@ -37,6 +38,7 @@ ch.pipeline().addLast(new NettyServerHandler()).addLast(new ProtocolEncoder()); } }) +// .addLast(new NettyServerHandler()) // .childHandler(new ChannelInitializer<Channel>(){ // // @Override diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 94f6cd6..b74cc54 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -99,10 +99,10 @@ android:backgroundTint="#2196F3" /> <com.google.android.material.button.MaterialButton - android:id="@+id/btn_force_switch" + android:id="@+id/btn_extend_fork" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="鎵嬪姩" + android:text="浼稿弶" android:layout_marginLeft="20sp" android:layout_centerVertical="true" android:layout_alignParentLeft="true" @@ -112,6 +112,22 @@ android:minWidth="10dp" android:layout_alignLeft="@+id/btn_rotatopn_left" android:layout_alignBottom="@+id/btn_go_forward" + android:backgroundTint="#2196F3" /> + + <com.google.android.material.button.MaterialButton + android:id="@+id/btn_collect_fork" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="鏀跺弶" + android:layout_marginLeft="20sp" + android:layout_centerVertical="true" + android:layout_alignParentLeft="true" + app:cornerRadius="5dp" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:minWidth="10dp" + android:layout_alignLeft="@+id/btn_rotatopn_left" + android:layout_alignBottom="@+id/btn_go_backward" android:backgroundTint="#2196F3" /> </RelativeLayout> @@ -127,6 +143,82 @@ android:layout_height="0dp" android:layout_weight="1"> + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:gravity="center"> + <com.google.android.material.button.MaterialButton + android:id="@+id/btn_model_switch" + android:layout_width="wrap_content" + android:layout_height="40dp" + android:text="鎵嬪姩妯″紡" + android:layout_centerHorizontal="true" + app:cornerRadius="5dp" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:minWidth="10dp" + android:textSize="10sp" + android:backgroundTint="#2196F3" /> + </LinearLayout> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:gravity="center"> + <com.google.android.material.button.MaterialButton + android:id="@+id/btn_force_switch" + android:layout_width="wrap_content" + android:layout_height="40dp" + android:text="寮�鍚己鍒�" + android:layout_centerHorizontal="true" + app:cornerRadius="5dp" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:minWidth="10dp" + android:textSize="10sp" + android:backgroundTint="#2196F3" /> + </LinearLayout> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:gravity="center"> + <com.google.android.material.button.MaterialButton + android:id="@+id/btn_single_switch" + android:layout_width="wrap_content" + android:layout_height="40dp" + android:text="鍗曡酱浣胯兘" + android:layout_centerHorizontal="true" + app:cornerRadius="5dp" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:minWidth="10dp" + android:textSize="10sp" + android:backgroundTint="#2196F3" /> + </LinearLayout> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:gravity="center"> + <com.google.android.material.button.MaterialButton + android:id="@+id/btn_function_switch" + android:layout_width="wrap_content" + android:layout_height="40dp" + android:text="鍔熻兘鍒囨崲" + android:layout_centerHorizontal="true" + app:cornerRadius="5dp" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:minWidth="10dp" + android:textSize="10sp" + android:backgroundTint="#2196F3" /> + </LinearLayout> + </LinearLayout> -- Gitblit v1.9.1