JAVA 串口数据拆包处理(多段分包数据合并)

/**
     * 数据拆包处理
     * @param readByte
     */
    private void unpackHandle(byte[] readByte) {
        if(readByte.length == 0){
            return;
        }
        log.info("原缓存中的数据:cacheBuffs-->" +cacheBuffs+"");
        List buffList = new ArrayList<>();
        if(!JudgeEmptyUtils.isEmpty(cacheBuffs)){
            buffList.addAll(cacheBuffs);
            //清空静态变量数据,释放内存
            cacheBuffs.clear();
            cacheBuffs = null;
            cacheBuffs = new ArrayList();
        }
        buffList.addAll(Bytes.asList(readByte));
        log.info("待处理的数据:buffList-->" +buffList+"");
        //获取起始符下标
        //Integer beginIndex = buffList.indexOf(MiiMessage.BEGIN_BYTES[0]);
        Integer beginIndex = buffList.indexOf(ByteAndHexUtil.hexToByteArray(portServerProperties.getBeginCode())[0]);
        //获取结束符下标
        //Integer endIndex = buffList.indexOf(MiiMessage.END_BYTES[0]);
        Integer endIndex = buffList.indexOf(ByteAndHexUtil.hexToByteArray(portServerProperties.getEndCode())[0]);
        //如果是异常指令直接丢弃
        if(beginIndex == -1){
            log.info("接收到不合法指令,直接丢弃不处理:buffList-->" +buffList+"");
            buffList.clear();
            buffList = null;
            buffList = new ArrayList<>();
            return;
        }else if(beginIndex != -1 && endIndex == -1){
            cacheBuffs.addAll(buffList);
            log.info("接收到有起始符没有结束符的指令,暂不处理,放入缓存:cacheBuffs-->" +cacheBuffs+"");
            return;
        }else if(endIndex != -1 && beginIndex > endIndex){
            buffList = buffList.subList(0, endIndex);
            log.info("截取不合法指令,直接丢弃不处理:buffList-->" +buffList+"");
            //确保起始符下标小于结束符下标
//            beginIndex = buffList.indexOf(MiiMessage.BEGIN_BYTES[0]);
//            endIndex = buffList.indexOf(MiiMessage.END_BYTES[0]);
            beginIndex= buffList.indexOf(ByteAndHexUtil.hexToByteArray(portServerProperties.getBeginCode())[0]);
            endIndex = buffList.indexOf(ByteAndHexUtil.hexToByteArray(portServerProperties.getEndCode())[0]);
            if(endIndex == -1){
                cacheBuffs.addAll(buffList);
                log.info("处理后的指令有起始符没有结束符,暂不处理,放入缓存:cacheBuffs-->" +cacheBuffs+"");
                return;
            }
        }
        if(beginIndex >= 0 &&  endIndex > beginIndex){
            //截取指令数据(从起始符到结束符)
            List<Byte> dataBuff = buffList.subList(beginIndex, endIndex + 1);
            byte[] msg = new byte[dataBuff.size()];
            int i = 0;
            for (Byte b : dataBuff) {
                msg[i] = b;
                i++;
            }
            if(msg.length > 0){
                //TODO 返回完整的返回数据交给消息协议解析
                log.info("完整数据"+ByteAndHexUtil.byteToStr(msg,msg.length));
                //serialportDataFactory.buildData(msg);
            }
        }
    }

public class ByteAndHexUtil {
    //  十六进制的字符串转换成16进制byte数组
    public static byte[] HexCommandtoByte(byte[] data) {
        if (data == null) {
            return null;
        }
        int nLength = data.length;

        String strTemString = new String(data, 0, nLength);
        String[] strings = strTemString.split(" ");
        nLength = strings.length;
        data = new byte[nLength];
        for (int i = 0; i < nLength; i++) {
            if (strings[i].length() != 2) {
                data[i] = 00;
                continue;
            }
            try {
                data[i] = (byte) Integer.parseInt(strings[i], 16);
            } catch (Exception e) {
                data[i] = 00;
                continue;
            }
        }

        return data;
    }

    //string转16进制
    public static String strToHexStr(String str) {

        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;

        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
            sb.append(' ');
        }
        return sb.toString().trim();
    }

    //16进制转byte
    public static byte[] hexToByteArray(String inHex) {
        int hexlen = inHex.length();
        byte[] result;
        if (hexlen % 2 == 1) {
            //奇数
            hexlen++;
            result = new byte[(hexlen / 2)];
            inHex = "0" + inHex;
        } else {
            //偶数
            result = new byte[(hexlen / 2)];
        }
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = hexToByte(inHex.substring(i, i + 2));
            j++;
        }
        return result;
    }

    public static byte hexToByte(String inHex) {
        return (byte) Integer.parseInt(inHex, 16);
    }


    //byte转String
    public static String bytetoString(byte[] bytearray) {
        String result = "";
        char temp;

        int length = bytearray.length;
        for (int i = 0; i < length; i++) {
            temp = (char) bytearray[i];
            result += temp;
        }
        return result;
    }

    //byte数组转HEX
    public static String bytesToHex(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() < 2) {
                sb.append(0);
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    //接收到的字节数组转换16进制字符串
    public static String byteToStr(byte[] b, int size) {
        String ret = "";
        for (int i = 0; i < size; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase() + " ";
        }
        return ret.substring(0, ret.length() - 1);
    }

    /**
     * int转byte数组
     */
    public static byte[] intToByteArray(int i) {
        byte[] result = new byte[2];
        // 由高位到低位
//        result[0] = (byte) ((i >> 24) & 0xFF);
//        result[1] = (byte) ((i >> 16) & 0xFF);
        result[0] = (byte) ((i >> 8) & 0xFF);
        result[1] = (byte) (i & 0xFF);
        return result;
    }

    /**
     * int到byte[] 由高位到低位
     * @param i 需要转换为byte数组的整行值。
     * @return byte数组
     */
    public static byte[] intToByte(int i) {
        byte[] result = new byte[4];
        result[0] = (byte)((i >> 24) & 0xFF);
        result[1] = (byte)((i >> 16) & 0xFF);
        result[2] = (byte)((i >> 8) & 0xFF);
        result[3] = (byte)(i & 0xFF);
        return result;
    }


    /**
     * byte数组转int
     * @param b
     * @param start
     * @param len
     * @return
     */
    public static int bytes2Int(byte[] b, int start, int len) {
        int sum = 0;
        int end = start + len;
        for (int i = start; i < end; i++) {
            int n = ((int) b[i]) & 0xff;
            n <<= (--len) * 8;
            sum += n;
        }
        return sum;
    }


    /**
     * 16进制转换10进制带符号
     */
    public static int toTen(String str) {
        return Integer.valueOf(str, 16).shortValue();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Android 中,可以通过使用 `SerialPort` 类来进行串口通信,其中可以使用 `InputStream` 来读取串口数据。在读取串口数据时,需要注意数据和拼接。 一般情况下,串口通信中的数据都是按照固定长度的数据进行传输的。因此,在读取串口数据时,可以先读取数据头,然后根据头中的信息来确定数据的长度,最后读取完整的数据。 以下是一个简单的示例代码,演示了如何在 Android 中进行串口数据和拼接: ```java public class SerialPortActivity extends AppCompatActivity { private SerialPort mSerialPort; private InputStream mInputStream; private final int PACKET_HEADER = 0xAA; // 数据头 private int mPacketLength = 0; // 数据长度 private byte[] mPacketData = new byte[1024]; // 数据数据 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_serial_port); try { // 打开串口 mSerialPort = new SerialPort(new File("/dev/ttyS1"), 115200, 0); mInputStream = mSerialPort.getInputStream(); } catch (IOException e) { e.printStackTrace(); } // 开启一个线程来读取串口数据 new Thread(new Runnable() { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { try { // 读取一个字节的数据 int data = mInputStream.read(); // 判断是否为头 if (data == PACKET_HEADER) { // 读取数据长度 mPacketLength = mInputStream.read(); // 读取数据数据 for (int i = 0; i < mPacketLength; i++) { mPacketData[i] = (byte) mInputStream.read(); } // 拼接完整的数据 byte[] packet = new byte[mPacketLength + 2]; packet[0] = (byte) PACKET_HEADER; packet[1] = (byte) mPacketLength; System.arraycopy(mPacketData, 0, packet, 2, mPacketLength); // 处理数据 handlePacket(packet); } } catch (IOException e) { e.printStackTrace(); } } } }).start(); } private void handlePacket(byte[] packet) { // 在这里处理完整的数据 // ... } @Override protected void onDestroy() { super.onDestroy(); // 关闭串口 if (mSerialPort != null) { mSerialPort.close(); } } } ``` 在上面的示例代码中,当读取到头后,先读取数据的长度,然后再读取数据数据。最后,使用 `System.arraycopy()` 方法将头和数据拼接成一个完整的数据,然后再将其传递给 `handlePacket()` 方法进行处理

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值