From 5bdad72f5d5077ca875dd03cfdaafb3d7aba93da Mon Sep 17 00:00:00 2001
From: whycq <913841844@qq.com>
Date: 星期五, 16 八月 2024 14:36:58 +0800
Subject: [PATCH] #
---
app/src/main/java/com/example/agvcontroller/action/RedisConstant.java | 38 ++++
app/src/main/java/com/example/agvcontroller/action/AckMsgBuilder.java | 44 +++++
app/src/main/java/com/example/agvcontroller/protocol/AGV_A1_DOWN.java | 16 ++
app/src/main/java/com/example/agvcontroller/action/CommonConstant.java | 10 +
app/src/main/java/com/example/agvcontroller/MainActivity.java | 34 ++++
app/src/main/java/com/example/agvcontroller/action/AGV_11_UP.java | 115 ++++++++++++++
app/src/main/java/com/example/agvcontroller/met/AbstractInboundHandler.java | 36 ++++
app/src/main/java/com/example/agvcontroller/socket/NettyServerHandler.java | 89 ++++++++--
app/src/main/java/com/example/agvcontroller/action/AgvCompleteType.java | 53 ++++++
app/src/main/java/com/example/agvcontroller/socket/NettyServer.java | 2
app/build.gradle | 1
11 files changed, 415 insertions(+), 23 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index ef29b47..7dcae09 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -37,6 +37,7 @@
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'org.greenrobot:eventbus:3.2.0'
+ implementation 'redis.clients:jedis:3.0.1'
implementation 'androidx.recyclerview:recyclerview:1.3.0'
implementation 'io.netty:netty-all:4.1.68.Final'
diff --git a/app/src/main/java/com/example/agvcontroller/MainActivity.java b/app/src/main/java/com/example/agvcontroller/MainActivity.java
index 72f66e2..b08e87c 100644
--- a/app/src/main/java/com/example/agvcontroller/MainActivity.java
+++ b/app/src/main/java/com/example/agvcontroller/MainActivity.java
@@ -23,10 +23,16 @@
import com.example.agvcontroller.utils.SnowflakeIdWorker;
import java.net.Socket;
+import java.sql.Time;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeoutException;
public class MainActivity extends AppCompatActivity {
+
+ public static final Map<String, Object> map = new ConcurrentHashMap();
private RecyclerView recyclerView;
private ItemAdapter itemAdapter;
@@ -45,22 +51,46 @@
private boolean isDowm = false;
private boolean isOpen = false;
- String substring = String.valueOf(new SnowflakeIdWorker().nextId()).substring(0,16);
+
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (isDowm) {
+ String substring = String.valueOf(new SnowflakeIdWorker().nextId()).substring(0,16);
AgvAction agvAction = new AgvAction<>(ForceSwitchAction.class)
.setAgvNo("1")
.setSerialNo(substring)
.setVal(1)
.bodySync((action) -> action.setPwd((short) 21));
+
nettyServerHandler.sendMessageToClient(clientId, agvAction); // 鍙戦�佹秷鎭埌瀹㈡埛绔�
handler.sendEmptyMessageDelayed(0, 100);
+
+ boolean result = false;
+ long timestamp = System.currentTimeMillis();
+
+ while (System.currentTimeMillis() - timestamp < 5000) {
+
+ Object o = map.get(substring);
+
+ if (null != o) {
+ result = true;
+ map.remove(o);
+ break;
+ }
+ }
+
+ if (result) {
+ // alert ok
+ } else {
+ throw new TimeoutException("瓒呮椂");
+ }
+
}
if (isOpen) {
+ String substring = String.valueOf(new SnowflakeIdWorker().nextId()).substring(0,16);
AgvAction agvAction = new AgvAction<>(ForceSwitchAction.class)
.setAgvNo("12")
.setSerialNo(substring)
@@ -99,7 +129,7 @@
if (vibrator != null && vibrator.hasVibrator()) {
vibrator.vibrate(500);
}
-
+ String substring = String.valueOf(new SnowflakeIdWorker().nextId()).substring(0,16);
AgvAction agvAction = new AgvAction<>(HandOutAction.class)
.setAgvNo("12")
.setSerialNo(substring)
diff --git a/app/src/main/java/com/example/agvcontroller/action/AGV_11_UP.java b/app/src/main/java/com/example/agvcontroller/action/AGV_11_UP.java
new file mode 100644
index 0000000..67fb01b
--- /dev/null
+++ b/app/src/main/java/com/example/agvcontroller/action/AGV_11_UP.java
@@ -0,0 +1,115 @@
+package com.example.agvcontroller.action;
+
+import com.example.agvcontroller.protocol.IMessageBody;
+import com.example.agvcontroller.protocol.Utils;
+import com.example.agvcontroller.socket.RadixTools;
+
+import java.io.Serializable;
+
+/**
+ * 鍔ㄤ綔瀹屾垚鏁版嵁鍖�
+ *
+ * Created by vincent on 2023/3/21
+ */
+public class AGV_11_UP implements IMessageBody, Serializable {
+
+ private static final long serialVersionUID = 8403019742104020004L;
+
+ @Override
+ public byte[] writeToBytes() {
+ return new byte[0];
+ }
+
+ @Override
+ public void readFromBytes(byte[] bytes) {
+// try {
+ this.serialNo = new String(Utils.sliceWithReverse(bytes, 0, 16));
+// } catch (UnsupportedEncodingException e) {
+// e.printStackTrace();
+// }
+ this.completeCode = Utils.slice(bytes, 16, 1)[0];
+ this.completeType = AgvCompleteType.query(this.completeCode);
+ this.qrCode = Utils.zeroFill(String.valueOf(RadixTools.bytesToInt(Utils.sliceWithReverse(bytes, 17, 4))), CommonConstant.QR_CODE_LEN);
+ this.direction = RadixTools.byteToShort(Utils.sliceWithReverse(bytes, 21,2));
+// this.locCode = new String(Utils.sliceWithReverse(bytes, 23, 16)).replaceAll("\\u0000", "");
+// this.boxCode = new String(Utils.sliceWithReverse(bytes, 39, 16)).replaceAll("\\u0000", "");
+ this.locCode = Utils.zeroFill(String.valueOf(RadixTools.bytesToInt(Utils.sliceWithReverse(bytes, 23, 4))), CommonConstant.QR_CODE_LEN);
+ this.boxCode = Utils.zeroFill(String.valueOf(RadixTools.bytesToInt(Utils.sliceWithReverse(bytes, 39, 4))), CommonConstant.QR_CODE_LEN);
+ }
+
+ private String serialNo;
+
+ // 瀹屾垚鍔ㄤ綔鐮�
+ private int completeCode;
+
+ private AgvCompleteType completeType;
+
+ // 鍦伴潰鐮� - 8浣�
+ private String qrCode;
+
+ // 杞﹀ご鏈濆悜
+ private short direction;
+
+ // 璐т綅浜岀淮鐮�
+ private String locCode;
+
+ public String getSerialNo() {
+ return serialNo;
+ }
+
+ public void setSerialNo(String serialNo) {
+ this.serialNo = serialNo;
+ }
+
+ public int getCompleteCode() {
+ return completeCode;
+ }
+
+ public void setCompleteCode(int completeCode) {
+ this.completeCode = completeCode;
+ }
+
+ public AgvCompleteType getCompleteType() {
+ return completeType;
+ }
+
+ public void setCompleteType(AgvCompleteType completeType) {
+ this.completeType = completeType;
+ }
+
+ public String getQrCode() {
+ return qrCode;
+ }
+
+ public void setQrCode(String qrCode) {
+ this.qrCode = qrCode;
+ }
+
+ public short getDirection() {
+ return direction;
+ }
+
+ public void setDirection(short direction) {
+ this.direction = direction;
+ }
+
+ public String getLocCode() {
+ return locCode;
+ }
+
+ public void setLocCode(String locCode) {
+ this.locCode = locCode;
+ }
+
+ public String getBoxCode() {
+ return boxCode;
+ }
+
+ public void setBoxCode(String boxCode) {
+ this.boxCode = boxCode;
+ }
+
+ // 鏂欑浜岀淮鐮�
+ private String boxCode;
+
+}
diff --git a/app/src/main/java/com/example/agvcontroller/action/AckMsgBuilder.java b/app/src/main/java/com/example/agvcontroller/action/AckMsgBuilder.java
new file mode 100644
index 0000000..e86e3c0
--- /dev/null
+++ b/app/src/main/java/com/example/agvcontroller/action/AckMsgBuilder.java
@@ -0,0 +1,44 @@
+package com.example.agvcontroller.action;
+
+import com.example.agvcontroller.protocol.AgvPackage;
+import com.example.agvcontroller.protocol.ProtocolType;
+import com.example.agvcontroller.protocol.ProtocolUtils;
+
+import java.util.logging.Logger;
+
+import io.netty.buffer.ByteBuf;
+
+/**
+ * 搴旂瓟鎶ユ枃寤洪�犺��
+ * Created by vincent on 2019-04-04
+ */
+public class AckMsgBuilder {
+
+// private static final Logger log = LoggerFactory.getLogger(AckMsgBuilder.class);
+
+ /**
+ * 鎴愬姛搴旂瓟
+ * @return ByteBuf
+ */
+ public static AgvPackage ofSuccess(AgvPackage original, ProtocolType ackType) {
+
+
+ return ProtocolUtils.installDownProtocol(
+
+ original.getHeader().getUniqueNo()
+
+ , ackType
+ );
+
+ }
+
+ /**
+ * 澶辫触搴旂瓟
+ * @return ByteBuf
+ */
+ public static ByteBuf ofFail(ByteBuf sourceBuff) {
+ return sourceBuff;
+ }
+
+
+}
diff --git a/app/src/main/java/com/example/agvcontroller/action/AgvCompleteType.java b/app/src/main/java/com/example/agvcontroller/action/AgvCompleteType.java
new file mode 100644
index 0000000..f274222
--- /dev/null
+++ b/app/src/main/java/com/example/agvcontroller/action/AgvCompleteType.java
@@ -0,0 +1,53 @@
+package com.example.agvcontroller.action;
+
+/**
+ * Agv鍔ㄤ綔瀹屾垚绫诲瀷
+ */
+public enum AgvCompleteType {
+
+ COMMON_COMPLETE(0x01, "鍒濆鍖栬嚜妫�鎴栬鍔ㄦ煡璇㈠畬鎴�"),
+
+ STRAIGHT_COMPLETE(0x02, "鐩磋璺緞瀹屾垚"),
+
+ TURN_CORNER_COMPLETE(0x03, "杞集瀹屾垚"),
+
+ RETURN_ZERO_OF_ROTATE_TELESCOPIC_COMPLETE(0x04, "鏃嬭浆浼哥缉褰掗浂瀹屾垚"),
+
+ TAKE_FROM_STORAGE_COMPLETE(0x05, "浠庢枡浠撳彇璐у畬鎴�"),
+
+ RELEASE_FROM_STORAGE_COMPLETE(0x06, "寰�鏂欎粨鏀捐揣瀹屾垚"),
+
+ TAKE_FROM_SHELVES_COMPLETE(0x07, "浠庤揣鏋跺彇璐у畬鎴�"),
+
+ RELEASE_FROM_SHELVES_COMPLETE(0x08, "寰�璐ф灦鏀捐揣瀹屾垚"),
+
+ SCAN_COMPLETE(0x09, "鎵弿璐ф灦鍜屾枡绠卞畬鎴�"),
+
+ DOCKING_CHARGE_COMPLETE(0x0C, "鍏呯數瀵规帴瀹屾垚"),
+
+ FULL_CHARGE_COMPLETE(0x0D, "鍏呮弧鐢�"),
+
+ STOP_RECENT_CODE_COMPLETE(0x0E, "鍋滃埌鏈�杩戜簩缁寸爜瀹屾垚"),
+
+ ENTIRE_PATH_COMPLETE(0x0F, "鏁翠釜璺緞鎵ц瀹屾垚"),
+
+ ;
+
+ private int code;
+ private String desc;
+
+ AgvCompleteType(int code, String desc) {
+ this.code = code;
+ this.desc = desc;
+ }
+
+ public static AgvCompleteType query(int completeCode) {
+ for (AgvCompleteType type : AgvCompleteType.values()) {
+ if (completeCode == type.code) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/app/src/main/java/com/example/agvcontroller/action/CommonConstant.java b/app/src/main/java/com/example/agvcontroller/action/CommonConstant.java
new file mode 100644
index 0000000..048ea67
--- /dev/null
+++ b/app/src/main/java/com/example/agvcontroller/action/CommonConstant.java
@@ -0,0 +1,10 @@
+package com.example.agvcontroller.action;
+
+/**
+ * Created by vincent on 2023/3/29
+ */
+public class CommonConstant {
+
+ public static final int QR_CODE_LEN = 8;
+
+}
diff --git a/app/src/main/java/com/example/agvcontroller/action/RedisConstant.java b/app/src/main/java/com/example/agvcontroller/action/RedisConstant.java
new file mode 100644
index 0000000..e84b232
--- /dev/null
+++ b/app/src/main/java/com/example/agvcontroller/action/RedisConstant.java
@@ -0,0 +1,38 @@
+package com.example.agvcontroller.action;
+
+/**
+ * Created by vincent on 2023/3/14
+ */
+public class RedisConstant {
+
+ public static final String AGV_CMD_DOWN_FLAG = "AGV_CMD_DOWN_FLAG";
+
+ public static final String AGV_CMD_UP_FLAG = "AGV_CMD_UP_FLAG";
+
+ public static final String AGV_ONLINE_FLAG = "AGV_ONLINE_FLAG";
+
+ public static final String AGV_COMPLETE_FLAG = "AGV_COMPLETE_FLAG";
+
+ public static final String AGV_DATA_FLAG = "AGV_DATA_FLAG";
+
+ public static final String AGV_FAULT_REPORT_FLAG = "AGV_FAULT_REPORT_FLAG";
+
+ public static final String DIGITAL_AGV_FLAG = "DIGITAL_AGV_FLAG";
+
+ public static final int CMD_TIMEOUT_LIMIT = 5000;
+
+ public static final String AGV_MAP_ASTAR_FLAG = "AGV_MAP_ASTAR_FLAG";
+
+ public static final String AGV_MAP_ASTAR_CODE_FLAG = "AGV_MAP_ASTAR_CODE_FLAG";
+
+ public static final String AGV_MAP_ASTAR_TURN_FLAG = "AGV_MAP_ASTAR_TURN_FLAG";
+
+ public static final String AGV_MAP_ASTAR_CDA_FLAG = "AGV_MAP_ASTAR_CDA_FLAG";
+
+ public static final String AGV_MAP_ASTAR_DYNAMIC_FLAG = "AGV_MAP_ASTAR_DYNAMIC_FLAG";
+
+ public static final String AGV_MAP_ASTAR_WAVE_FLAG = "AGV_MAP_ASTAR_WAVE_FLAG";
+
+ public static final String AGV_TRAFFIC_JAM_FLAG = "AGV_TRAFFIC_JAM_FLAG";
+
+}
diff --git a/app/src/main/java/com/example/agvcontroller/met/AbstractInboundHandler.java b/app/src/main/java/com/example/agvcontroller/met/AbstractInboundHandler.java
new file mode 100644
index 0000000..7fd263e
--- /dev/null
+++ b/app/src/main/java/com/example/agvcontroller/met/AbstractInboundHandler.java
@@ -0,0 +1,36 @@
+package com.example.agvcontroller.met;
+
+import com.example.agvcontroller.protocol.AgvPackage;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.util.ReferenceCountUtil;
+
+/**
+ * netty handler澧炲己鍣�
+ * 璁捐妯″紡: 閫傞厤鍣ㄦā寮�
+ * Created by vincent on 2019-04-06
+ */
+public abstract class AbstractInboundHandler<T> extends ChannelInboundHandlerAdapter {
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object obj) throws Exception {
+ @SuppressWarnings("unchecked")
+ T t = (T) obj;
+ if (channelRead0(ctx, t)) {
+ ctx.fireChannelRead(t);
+ } else {
+ // 绠¢亾涓柇锛宖ireChannelRead鏈墽琛岋紝闇�瑕佹墜鍔ㄩ噴鏀惧爢澶栧唴瀛�
+ if (obj instanceof AgvPackage){
+ AgvPackage pac = (AgvPackage) obj;
+ if (pac.getSourceBuff().refCnt() > 0) {
+ pac.getSourceBuff().skipBytes(pac.getSourceBuff().readableBytes());
+ ReferenceCountUtil.release(pac.getSourceBuff());
+ }
+ }
+ }
+ }
+
+ protected abstract boolean channelRead0(ChannelHandlerContext ctx, T t) throws Exception;
+
+}
diff --git a/app/src/main/java/com/example/agvcontroller/protocol/AGV_A1_DOWN.java b/app/src/main/java/com/example/agvcontroller/protocol/AGV_A1_DOWN.java
index 7cdfe5d..b51952f 100644
--- a/app/src/main/java/com/example/agvcontroller/protocol/AGV_A1_DOWN.java
+++ b/app/src/main/java/com/example/agvcontroller/protocol/AGV_A1_DOWN.java
@@ -21,6 +21,22 @@
}
+ public byte getAckSign() {
+ return ackSign;
+ }
+
+ public void setAckSign(byte ackSign) {
+ this.ackSign = ackSign;
+ }
+
+ public byte[] getTemp() {
+ return temp;
+ }
+
+ public void setTemp(byte[] temp) {
+ this.temp = temp;
+ }
+
private byte ackSign = 0x11;
private byte[] temp = new byte[4];
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 1f91141..278bac0 100644
--- a/app/src/main/java/com/example/agvcontroller/socket/NettyServer.java
+++ b/app/src/main/java/com/example/agvcontroller/socket/NettyServer.java
@@ -35,7 +35,7 @@
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
- ch.pipeline().addLast(new NettyServerHandler()).addLast(new ProtocolEncoder());
+ ch.pipeline().addLast(new ProtocolEncoder()).addLast(new ProtocolDecoder(4096)).addLast(new NettyServerHandler());
}
})
// .addLast(new NettyServerHandler())
diff --git a/app/src/main/java/com/example/agvcontroller/socket/NettyServerHandler.java b/app/src/main/java/com/example/agvcontroller/socket/NettyServerHandler.java
index 1bcb965..f27d329 100644
--- a/app/src/main/java/com/example/agvcontroller/socket/NettyServerHandler.java
+++ b/app/src/main/java/com/example/agvcontroller/socket/NettyServerHandler.java
@@ -1,30 +1,34 @@
package com.example.agvcontroller.socket;
-import java.nio.charset.StandardCharsets;
+
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
import android.util.Log;
import com.example.agvcontroller.Item;
+import com.example.agvcontroller.MainActivity;
+import com.example.agvcontroller.action.AGV_11_UP;
+import com.example.agvcontroller.action.AckMsgBuilder;
+import com.example.agvcontroller.met.AbstractInboundHandler;
+import com.example.agvcontroller.protocol.AGV_A1_DOWN;
import com.example.agvcontroller.protocol.AgvAction;
+import com.example.agvcontroller.protocol.AgvPackage;
+import com.example.agvcontroller.protocol.ProtocolType;
import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
-public class NettyServerHandler extends ChannelInboundHandlerAdapter {
+public class NettyServerHandler extends AbstractInboundHandler<AgvPackage> {
private static final String TAG = "NettyServerHandler";
private static ConcurrentHashMap<String, Channel> channelMap = new ConcurrentHashMap<>();
+
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
@@ -42,22 +46,53 @@
Log.d(TAG, "Client disconnected: " + clientId);
}
+// @Override
+// public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+// // 澶勭悊鎺ユ敹鍒扮殑娑堟伅
+// ByteBuf byteBuf = (ByteBuf) msg;
+// try {
+// while (byteBuf.isReadable()) {
+// byte[] bytes = new byte[byteBuf.readableBytes()];
+// byteBuf.readBytes(bytes);
+// String hexString = bytesToHex(bytes);
+// // 鑾峰彇agv淇℃伅 娣诲姞鍒發ist涓�
+// Log.d(TAG, "ctx: " + ctx.channel().remoteAddress().toString() );
+// Log.d(TAG, "Received: " + hexString);
+// }
+// } finally {
+// byteBuf.release();
+// }
+// }
+
@Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- // 澶勭悊鎺ユ敹鍒扮殑娑堟伅
- ByteBuf byteBuf = (ByteBuf) msg;
- try {
- while (byteBuf.isReadable()) {
- byte[] bytes = new byte[byteBuf.readableBytes()];
- byteBuf.readBytes(bytes);
- String hexString = bytesToHex(bytes);
- // 鑾峰彇agv淇℃伅 娣诲姞鍒發ist涓�
- Log.d(TAG, "ctx: " + ctx.channel().remoteAddress().toString() );
- Log.d(TAG, "Received: " + hexString);
- }
- } finally {
- byteBuf.release();
+ protected boolean channelRead0(ChannelHandlerContext ctx, AgvPackage pac) throws Exception {
+
+ String serialNum = pac.getHeader().getSerialNum();
+ // ack
+ ProtocolType ackType = isNeedAck(pac);
+ final String uniqueNo = pac.getHeader().getUniqueNo();
+ label : switch (pac.getHeader().getProtocolType()){
+ case ACTION_COMPLETE: // 鍔ㄤ綔瀹屾垚鏁版嵁鍖�
+
+
+ AGV_11_UP agv_11_up = (AGV_11_UP) pac.getBody().getMessageBody();
+// redis.push(RedisConstant.AGV_COMPLETE_FLAG, AgvProtocol.build(uniqueNo).setMessageBody(agv_11_up));
+
+ // 鍔ㄤ綔瀹屾垚搴旂瓟
+ if (null != ackType) {
+ AgvPackage ackPac = AckMsgBuilder.ofSuccess(pac, ackType);
+
+ AGV_A1_DOWN agv_a1_down = (AGV_A1_DOWN) ackPac.getBody().getMessageBody();
+ agv_a1_down.setAckSign((byte) agv_11_up.getCompleteCode());
+
+ ctx.writeAndFlush(ackPac);
+ }
+
+ MainActivity.map.put(serialNum, Boolean.TRUE);
+
+ break label;
}
+ return false;
}
private String bytesToHex(byte[] bytes) {
@@ -109,4 +144,18 @@
ctx.close();
}
+ /**
+ * 鏈嶅姟鍣ㄦ槸鍚﹂渶瑕佸簲绛�
+ */
+ public static ProtocolType isNeedAck(AgvPackage pac) {
+ switch (pac.getHeader().getProtocolType()) {
+ case ACTION_COMPLETE:
+ return ProtocolType.ACTION_SUCCESS_ACK;
+ case LOGIN_REPORT:
+ return ProtocolType.LOGIN_ACK;
+ default:
+ return null;
+ }
+ }
+
}
--
Gitblit v1.9.1