#
whycq
2024-08-14 0d580a2b6e4ac2013ba5cbab046bdabf956b301b
#
6个文件已修改
8个文件已添加
536 ■■■■■ 已修改文件
.idea/.name 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/MainActivity.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/StartActivity.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/protocol/AGV_02_DOWN.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/protocol/AgvAction.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/protocol/AgvActionItem.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/protocol/DataSupport.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/protocol/ForceSwitchAction.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/protocol/HandleCmdType.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/protocol/IActionBody.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/protocol/ProtocolEncoder.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/socket/NettyServer.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/socket/NettyServerHandler.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/agvcontroller/socket/RadixTools.java 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/.name
New file
@@ -0,0 +1 @@
AGVController
app/src/main/java/com/example/agvcontroller/MainActivity.java
@@ -15,6 +15,8 @@
import android.view.View;
import android.widget.Button;
import com.example.agvcontroller.protocol.AgvAction;
import com.example.agvcontroller.protocol.ForceSwitchAction;
import com.example.agvcontroller.protocol2.AgvPackage;
import com.example.agvcontroller.protocol2.PackagePart;
import com.example.agvcontroller.socket.NettyServerHandler;
@@ -43,11 +45,21 @@
    private Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            AgvAction agvAction = new AgvAction<>(ForceSwitchAction.class)
                    .setAgvNo("1")
                    .setSerialNo("asdsadsadsad")
                    .setVal(1)
                    .bodySync((action) -> action.setPwd((short) 21));
            // 在这里进行打印输出
            System.out.println("打印输出");
            if (isDowm) {
                byte[] message2 = new byte[]{0x01, 0x02, 0x03, 0x06}; // 示例消息
                nettyServerHandler.sendMessageToClient(clientId, message2); // 发送消息到客户端
                System.out.println(agvAction);
//                byte[] message2 = new byte[]{0x01, 0x02, 0x03, 0x06}; // 示例消息
                nettyServerHandler.sendMessageToClient(clientId, agvAction); // 发送消息到客户端
                handler.sendEmptyMessageDelayed(0, 100);
            }
            return false;
app/src/main/java/com/example/agvcontroller/StartActivity.java
@@ -52,7 +52,7 @@
            }
        });
        socketManager = new SocketManager();
        socketManager.startServer(8024);
        socketManager.startServer(8022);
    }
    @Subscribe(threadMode = ThreadMode.MAIN)
app/src/main/java/com/example/agvcontroller/protocol/AGV_02_DOWN.java
@@ -42,4 +42,35 @@
    // 动作参数
    private ICommandBody commandBody;
    public String getSerialNo() {
        return serialNo;
    }
    public void setSerialNo(String serialNo) {
        this.serialNo = serialNo;
    }
    public int getCmdCode() {
        return cmdCode;
    }
    public void setCmdCode(int cmdCode) {
        this.cmdCode = cmdCode;
    }
    public int getVal() {
        return val;
    }
    public void setVal(int val) {
        this.val = val;
    }
    public ICommandBody getCommandBody() {
        return commandBody;
    }
    public void setCommandBody(ICommandBody commandBody) {
        this.commandBody = commandBody;
    }
}
app/src/main/java/com/example/agvcontroller/protocol/AgvAction.java
New file
@@ -0,0 +1,124 @@
package com.example.agvcontroller.protocol;
import com.example.agvcontroller.socket.NettyServerHandler;
import com.example.agvcontroller.socket.RadixTools;
import org.json.JSONObject;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by vincent on 2023/3/14
 */
@SuppressWarnings("all")
public class AgvAction<T extends IActionBody> implements Serializable {
    private static final long serialVersionUID = -1701520567284510548L;
    private String agvNo;
    private String serialNo;
    private int val;
    private T actionBody;
    private HandleCmdType handleCmdType;
    public byte[] writeToBytes() {
//        byte[] bytes = new
        String serialNo = Utils.zeroFill(this.serialNo, 16);
        byte[] serialNoBytes = Utils.reverse(serialNo.getBytes());  // 流水号
        byte cmdCode = (byte) handleCmdType.cmdCode;    // 命令码
        byte valByte = (byte) val;    // 属性值
        byte[] bytes = actionBody.writeToBytes();   // 命令参数
        return new byte[12];
    }
    void readFromBytes(byte[] messageBodyBytes) {
    }
    public AgvAction(Class<T> clazz) {
        try {
            actionBody = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.handleCmdType = HandleCmdType.find(actionBody.getClass());
        if (null == handleCmdType) {
            throw new RuntimeException(clazz.getName() + "检索 HandleCmdType 枚举失败");
        }
    }
    public AgvAction<T> setAgvNo(String agvNo) {
        this.agvNo = agvNo;
        return this;
    }
    public AgvAction<T> setSerialNo(String serialNo) {
        this.serialNo = serialNo;
        return this;
    }
    public AgvAction<T> bodySync(DataSupport<T> dataSupport) {
        dataSupport.sync(this.actionBody);
        return this;
    }
    public static void main(String[] args) {
        AgvAction agvAction = new AgvAction<>(ForceSwitchAction.class)
                .setAgvNo("1")
                .setSerialNo("asdsadsadsad")
                .setVal(1)
                .bodySync((action) -> action.setPwd((short) 21));
        NettyServerHandler.sendMessageToClient("123213", agvAction);
    }
    public String getAgvNo() {
        return agvNo;
    }
    public String getSerialNo() {
        return serialNo;
    }
    public T getActionBody() {
        return actionBody;
    }
    public void setActionBody(T actionBody) {
        this.actionBody = actionBody;
    }
    public HandleCmdType getHandleCmdType() {
        return handleCmdType;
    }
    public void setHandleCmdType(HandleCmdType handleCmdType) {
        this.handleCmdType = handleCmdType;
    }
    public int getVal() {
        return val;
    }
    public AgvAction<T> setVal(int val) {
        this.val = val;
        return this;
    }
}
app/src/main/java/com/example/agvcontroller/protocol/AgvActionItem.java
New file
@@ -0,0 +1,63 @@
package com.example.agvcontroller.protocol;
import java.io.Serializable;
/**
 * 路径包 - 路径点
 * Created by vincent on 2023/3/14
 */
//@Data
public class AgvActionItem<T extends IActionBody> implements Serializable {
    private static final long serialVersionUID = -6988765550778795176L;
    // 地面码
    private String qrCode;
    // 动作码
//    private AgvActionCmdType actionCmdType;
    // 属性值
    private int val;
    // 动作参数
    private T actionBody;
    public AgvActionItem() {
    }
//    public AgvActionItem(Class<T> clazz) {
//        try {
//            actionBody = clazz.newInstance();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        this.actionCmdType = AgvActionCmdType.find(actionBody.getClass());
//        if (null == actionCmdType) {
//            throw new CoolException(clazz.getName() + "检索 AgvActionCmdType 枚举失败");
//        }
//    }
    public AgvActionItem<T> setQrCode(String qrCode) {
        this.qrCode = qrCode;
        return this;
    }
//    public AgvActionItem<T> setActionCmdType(AgvActionCmdType actionCmdType) {
//        this.actionCmdType = actionCmdType;
//        return this;
//    }
    public AgvActionItem<T> setVal(int val) {
        this.val = val;
        return this;
    }
    public AgvActionItem<T> bodySync(DataSupport<T> dataSupport) {
        dataSupport.sync(this.actionBody);
        return this;
    }
}
app/src/main/java/com/example/agvcontroller/protocol/DataSupport.java
New file
@@ -0,0 +1,7 @@
package com.example.agvcontroller.protocol;
public interface DataSupport<T> {
    void sync(T t);
}
app/src/main/java/com/example/agvcontroller/protocol/ForceSwitchAction.java
New file
@@ -0,0 +1,28 @@
package com.example.agvcontroller.protocol;
import java.io.Serializable;
public class ForceSwitchAction implements IActionBody, Serializable {
    private static final long serialVersionUID = -3250235107705010316L;
    private Short pwd;
    @Override
    public byte[] writeToBytes() {
        return new byte[0];
    }
    @Override
    public void readFromBytes(byte[] messageBodyBytes) {
    }
    public Short getPwd() {
        return pwd;
    }
    public void setPwd(Short pwd) {
        this.pwd = pwd;
    }
}
app/src/main/java/com/example/agvcontroller/protocol/HandleCmdType.java
New file
@@ -0,0 +1,29 @@
package com.example.agvcontroller.protocol;
public enum HandleCmdType {
    FORCE_SWITCH(0x80, "开启/关闭强制", ForceSwitchAction.class),
    ;
    public int cmdCode;
    public String desc;
    public Class<? extends IActionBody> cls;
    HandleCmdType(int cmdCode, String desc, Class<? extends IActionBody> cls) {
        this.cmdCode = cmdCode;
        this.desc = desc;
        this.cls = cls;
    }
    public static HandleCmdType find(Class<? extends IActionBody> cls) {
        for (HandleCmdType value : HandleCmdType.values()) {
            if (value.cls.equals(cls)) {
                return value;
            }
        }
        return null;
    }
}
app/src/main/java/com/example/agvcontroller/protocol/IActionBody.java
New file
@@ -0,0 +1,12 @@
package com.example.agvcontroller.protocol;
/**
 * 动作参数
 */
public interface IActionBody {
    byte[] writeToBytes();
    void readFromBytes(byte[] messageBodyBytes);
}
app/src/main/java/com/example/agvcontroller/protocol/ProtocolEncoder.java
@@ -1,5 +1,7 @@
package com.example.agvcontroller.protocol;
import com.example.agvcontroller.socket.RadixTools;
import java.util.logging.Logger;
import io.netty.buffer.ByteBuf;
@@ -32,6 +34,39 @@
        } else if (obj instanceof byte[]){
            out.writeBytes((byte[]) obj);
        } else if (obj instanceof AgvAction<?>){
            AgvAction action = (AgvAction)obj;
            String uniqueNo = action.getAgvNo();
            byte[] uniqueNoBytes = RadixTools.intToBytes(Integer.parseInt(uniqueNo));   // uniqueno
            byte[] bodyBytes = action.writeToBytes();
            int len = PackagePart.UNIQUENO.getLen()     // len
                    + PackagePart.TIMESTAMP.getLen()
                    + PackagePart.COMMAND_MARK.getLen()
                    + bodyBytes.length;
            out.writeByte((byte)0xEE)         // symbol
                    .writeShortLE(len)
                    .writeBytes(Utils.reverse(uniqueNoBytes))       // uniqueno
                    .writeIntLE((int) (System.currentTimeMillis() / 1000))   // timestamp
                    .writeByte(ProtocolPojoType.ACTION_COMMAND.protocolType.getCode()) // type
                    .writeBytes(bodyBytes)                          // body
                    .writeShort((short)0)                 // valid
            ;
            int validCode = ValidUtil.calculateValidByteFromBuff(out);
            out.resetReaderIndex();
            out.writerIndex(out.readableBytes() - 2);
            out.writeShortLE(validCode);
        } else if (obj instanceof AgvPackage){
            AgvPackage pac = (AgvPackage)obj;
app/src/main/java/com/example/agvcontroller/socket/NettyServer.java
@@ -1,5 +1,7 @@
package com.example.agvcontroller.socket;
import com.example.agvcontroller.protocol.ProtocolEncoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
@@ -32,9 +34,16 @@
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new NettyServerHandler());
                            ch.pipeline().addLast(new NettyServerHandler()).addLast(new ProtocolEncoder());
                        }
                    })
//                    .childHandler(new ChannelInitializer<Channel>(){
//
//                        @Override
//                        protected void initChannel(Channel ch) throws Exception {
//                            ch.pipeline().addLast(new ProtocolEncoder());
//                        }
//                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);
app/src/main/java/com/example/agvcontroller/socket/NettyServerHandler.java
@@ -11,6 +11,7 @@
import android.util.Log;
import com.example.agvcontroller.Item;
import com.example.agvcontroller.protocol.AgvAction;
import org.greenrobot.eventbus.EventBus;
@@ -89,6 +90,19 @@
        }
    }
    public static void sendMessageToClient(String clientId, AgvAction<?> action) {
        Channel channel = channelMap.get(clientId);
        if (channel != null && channel.isActive()) {
            channel.writeAndFlush(action);
        } else {
            Log.d(TAG, "Client " + clientId + " is not connected");
        }
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
app/src/main/java/com/example/agvcontroller/socket/RadixTools.java
New file
@@ -0,0 +1,163 @@
package com.example.agvcontroller.socket;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
/**
 * radix tools
 * Created by vincent on 2018/10/6
 */
public class RadixTools {
    public static void main(String[] args) {
        String s = RadixTools.toBinaryString((byte) 1);
        System.out.println(s);
        for(int i=s.length()-1;i>=0;i--){
            char c=s.charAt(i);
            if (i == 7 && c =='1'){
                System.out.println("===");
            }
        }
    }
    /************************************** BinaryString **********************************************/
    public static String toBinaryString(byte b){
        return Long.toBinaryString((b & 0xFF) + 0x100).substring(1);
    }
    public static String toBinaryString(byte[] bytes){
        StringBuilder sb = new StringBuilder();
        for (byte aByte : bytes) {
            sb.append(Long.toBinaryString((aByte & 0xFF) + 0x100).substring(1));
        }
        return sb.toString();
    }
    /************************************** HexString **********************************************/
    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }
    public static String bytesToHexStr(byte[] bytes){
        StringBuilder buf = new StringBuilder(bytes.length * 2);
        for(byte b : bytes) {
            buf.append(String.format("%02x", b & 0xff));
        }
        return buf.toString();
    }
    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }
    /************************************** String **********************************************/
    public static String bytesToStr(byte[] bytes){
        return bytesToStr(bytes, Charset.forName("gbk"));
    }
    public static String bytesToStr(byte[] bytes, Charset charset){
        return new String(bytes, charset).trim().toUpperCase();
    }
    public static byte[] strToBytes(String str) throws UnsupportedEncodingException {
        return str.getBytes("gbk");
    }
    /************************************** long **********************************************/
    public static byte[] longToBytes(long number) {
        long temp = number;
        byte[] b = new byte[8];
        for (int i = 0; i < b.length; i++) {
            b[i] = new Long(temp & 0xff).byteValue();// 将最低位保存在最低位
            temp = temp >> 8; // 向右移8位
        }
        return b;
    }
    public static long bytesToLong(byte[] bytes) {
        long s = 0;
        long s0 = bytes[0] & 0xff;// 最低位
        long s1 = bytes[1] & 0xff;
        long s2 = bytes[2] & 0xff;
        long s3 = bytes[3] & 0xff;
        long s4 = bytes[4] & 0xff;// 最低位
        long s5 = bytes[5] & 0xff;
        long s6 = bytes[6] & 0xff;
        long s7 = bytes[7] & 0xff;
        // s0不变
        s1 <<= 8;
        s2 <<= 16;
        s3 <<= 24;
        s4 <<= 8 * 4;
        s5 <<= 8 * 5;
        s6 <<= 8 * 6;
        s7 <<= 8 * 7;
        s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7;
        return s;
    }
    /************************************** int **********************************************/
    public static byte[] intToBytes(int n) {
        byte[] b = new byte[4];
        b[3] = (byte) (n & 0xff);
        b[2] = (byte) (n >> 8 & 0xff);
        b[1] = (byte) (n >> 16 & 0xff);
        b[0] = (byte) (n >> 24 & 0xff);
        return b;
    }
    public static int bytesToInt(byte[] b) {
        int s = 0;
        int s0 = b[0] & 0xff;// 最低位
        int s1 = b[1] & 0xff;
        int s2 = b[2] & 0xff;
        int s3 = b[3] & 0xff;
        s0 <<= 24;
        s1 <<= 16;
        s2 <<= 8;
        s = s0 | s1 | s2 | s3;
        return s;
    }
    /************************************** short **********************************************/
    public static short byteToShort(byte[] b) {
        short s = 0;
        short s0 = (short) (b[1] & 0xff);// 最低位
        short s1 = (short) (b[0] & 0xff);
        s1 <<= 8;
        s = (short) (s0 | s1);
        return s;
    }
    public static byte[] shortToByte(short s){
        byte[] b = new byte[2];
        for(int i = 0; i < 2; i++){
            int offset = 16 - (i+1)*8; //因为byte占4个字节,所以要计算偏移量
            b[i] = (byte)((s >> offset)&0xff); //把16位分为2个8位进行分别存储
        }
        return b;
    }
}