Android串口开发之数据拼包——解决串口数据被分割的问题

1,872 阅读2分钟

一、前言

最近公司开了一个新项目,新项目有新设备也就意味着新的协议的对接,本来一切顺顺利利的进行,不过这次的设备数据传输出现了点问题,一段并不长的数据被分割成了两段传给我这边。

其实数据量并不大,可以一次性传过来的,可惜设备都已经订好了没法变动底层的代码了,也很无奈,于是将之前封装的串口读写库加了一个可选的拼包功能。

二、原理和流程图

image

跟之前的区别主要还是SerialThread读取流的方式的区别

由原本的等待流反馈数据的被动等待,改为了不断轮询判断流中数据大小,如果有数据则拼接至已有的readBytes数组

直到流中没有数据后,便将数据回调给接口

三、功能的实现

(一)轮询读取函数的实现

在SerialPortReadThread中写了个死循环,不断判断inputStream中的数据大小

    /**
     * 轮询读取,判断inputStream中是否还有数据,还有就拼接
     * */
    private void splicingRead(){
        while (!isInterrupted()) {
            if (null == mInputStream) {
                return;
            }

            Log.i(TAG, "run: ");
            int size = 0;

            try {
                /** 获取流中数据的量*/
                int i = mInputStream.available();
                if (i == 0) {
                    size = 0;
                } else {
                    /** 流中有数据,则添加到临时数组中*/
                    size = mInputStream.read(mReadBuffer);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (size > 0) {
                /** 发现有信息后就追加到临时变量*/
                Log.i("SerialPortReadThread", size + "");
                readBytes = DataUtil.arrayAppend(readBytes, mReadBuffer, size);
                Log.i("SerialPortReadThread", DataUtil.bytesToHexString(readBytes, readBytes.length));
            } else {
                /** 没有需要追加的数据了,回调*/
                if (readBytes != null) {
                    onDataReceived(readBytes);
                }

                /** 清空,等待下个信息单元*/
                readBytes = null;
            }

            SystemClock.sleep(50);

        }
    }

(二)如何在项目中使用

现在gradle中添加依赖

maven { url "https://jitpack.io" }
implementation 'com.github.Giftedcat:AndroidSerialPortManager:v1.0.2'

在项目中使用时,和之前的区别就是多了一个readType的参数 可以传递 SerialPortManager.NORMAL

        serialPortManager = new SerialPortManager(new File("/dev/ttyS4"), 9600)
                .setOnSerialPortDataListener(new OnSerialPortDataListener() {
                    @Override
                    public void onDataReceived(final byte[] bytes) {
                        /** 接收到串口数据*/
                    }
                });

或者 SerialPortManager.SPLICING

        serialPortManager = new SerialPortManager(new File("/dev/ttyS4"), 9600, SerialPortManager.SPLICING)
                .setOnSerialPortDataListener(new OnSerialPortDataListener() {
                    @Override
                    public void onDataReceived(final byte[] bytes) {
                        /** 接收到串口数据*/
                    }
                });

一种是常规的读取方式,另一种就是这次的拼包的读取方式 具体使用哪一种可以根据实际情况选择

四、结语

有问题和建议都可以在评论区给我留言

源码地址:github.com/Giftedcat/A…