Android蓝牙输入流实时读取

Android蓝牙输入流实时读取,android,bluetooth,inputstream,Android,Bluetooth,Inputstream,我正在开发一个Android应用程序,它通过蓝牙接收实时数据并在屏幕上绘图 数据是陀螺传感器位置信息。我从定制的飞思卡尔Kinetis K10微控制器板(由我自己设计和测试)发送。对于蓝牙通信,我使用HC-05蓝牙模块 数据格式如下: 字节_1:位置标识字节,始终等于-128 字节2:轴1的位置 字节_3:轴2的位置 字节4:轴3的位置 我以特定的顺序连续发送这4个字节。我每5毫秒发送4字节的数据包,发送数据包大约需要4.7毫秒(9600波特率)。 从微控制器输出的数据在准确性和定时方面是完美的

我正在开发一个Android应用程序,它通过蓝牙接收实时数据并在屏幕上绘图

数据是陀螺传感器位置信息。我从定制的飞思卡尔Kinetis K10微控制器板(由我自己设计和测试)发送。对于蓝牙通信,我使用HC-05蓝牙模块

数据格式如下:

字节_1:位置标识字节,始终等于-128

字节2:轴1的位置

字节_3:轴2的位置

字节4:轴3的位置

我以特定的顺序连续发送这4个字节。我每5毫秒发送4字节的数据包,发送数据包大约需要4.7毫秒(9600波特率)。 从微控制器输出的数据在准确性和定时方面是完美的(用逻辑分析仪检查)

问题是,当从手机接收数据时,一些字节似乎丢失了。下面是代码的一部分,我正在读取InputStream:

private class ConnectedThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;

    public ConnectedThread(BluetoothSocket socket) {
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) {
            Log.e("Printer Service", "temp sockets not created", e);
        }
        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

    @Override
    public void run() {

        Log.i("BluetoothService", "BEGIN mConnectedThread");
        byte[] buffer = new byte[4];
        int bytes;

        while (true) {

                try {

                    bytes = mmInStream.read(buffer);

                    int position = 0;

                    if(buffer[0] == -128) {
                        if(bytes >= 2) {
                            sendArray.errorTilt = buffer[1];
                        }
                        if(bytes >= 3) {
                            sendArray.errorRoll = buffer[2];
                        }
                        if(bytes == 4) {
                            sendArray.errorPan = buffer[3];
                        }
                    }
                    else if(buffer[1] == -128) {
                        position = 1;
                        if(bytes >= 3) {
                            sendArray.errorTilt = buffer[2];
                        }
                        if(bytes == 4) {
                            sendArray.errorRoll = buffer[3];
                        }
                        if(bytes >= 2) {
                            sendArray.errorPan = buffer[0];
                        }
                    }
                    else if(buffer[2] == -128 && bytes >= 3) {
                        position = 2;
                        sendArray.errorRoll = buffer[0];
                        sendArray.errorPan = buffer[1];
                        if(bytes == 4) {
                            sendArray.errorTilt = buffer[3];
                        }
                    }
                    else if(buffer[3] == -128 && bytes == 4) {
                        position = 3;
                        sendArray.errorTilt = buffer[0];
                        sendArray.errorRoll = buffer[1];
                        sendArray.errorPan = buffer[2];
                    }

                    if(position <= bytes && bytes > 1) {
                        sendArray.errorUpdate = true;
                    }

                } catch (Exception e) {

                    e.printStackTrace();
                    connectionLost();
                    BluetoothService.this.stop();
                    break;
                }
        }
    }


    public void write(int oneByte) {
        try {
            mmOutStream.write(oneByte);

        } catch (IOException e) {
            Log.e("BluetoothService", "Exception during write", e);
        }
    }

    public void cancel() {
        try {
            mmSocket.close();

        } catch (IOException e) {
            Log.e("BluetoothService", "close() of connect socket failed", e);
        }
    }
}
私有类ConnectedThread扩展线程{
私人最终蓝牙插座mmSocket;
私有最终输入流mmInStream;
私有最终输出流mmOutStream;
公共连接线程(BluetoothSocket){
mmSocket=插座;
InputStream tmpIn=null;
OutputStream tmpOut=null;
试一试{
tmpIn=socket.getInputStream();
tmpOut=socket.getOutputStream();
}捕获(IOE异常){
Log.e(“打印机服务”,“未创建临时套接字”,e);
}
mmInStream=tmpIn;
mmOutStream=tmpOut;
}
@凌驾
公开募捐{
Log.i(“BluetoothService”、“BEGIN McConnectedThread”);
字节[]缓冲区=新字节[4];
整数字节;
while(true){
试一试{
字节=mmInStream.read(缓冲区);
int位置=0;
如果(缓冲区[0]==-128){
如果(字节>=2){
sendArray.errorTilt=缓冲区[1];
}
如果(字节>=3){
sendArray.errorRoll=缓冲区[2];
}
如果(字节==4){
sendArray.errorPan=缓冲区[3];
}
}
else if(缓冲区[1]=-128){
位置=1;
如果(字节>=3){
sendArray.errorTilt=缓冲区[2];
}
如果(字节==4){
sendArray.errorRoll=缓冲区[3];
}
如果(字节>=2){
sendArray.errorPan=缓冲区[0];
}
}
else if(缓冲区[2]=-128&&bytes>=3){
位置=2;
sendArray.errorRoll=缓冲区[0];
sendArray.errorPan=缓冲区[1];
如果(字节==4){
sendArray.errorTilt=缓冲区[3];
}
}
else if(缓冲区[3]=-128&&字节==4){
位置=3;
sendArray.errorTilt=缓冲区[0];
sendArray.errorRoll=缓冲区[1];
sendArray.errorPan=缓冲区[2];
}
如果(位置1){
sendArray.errorUpdate=true;
}
}捕获(例外e){
e、 printStackTrace();
connectionLost();
BluetoothService.this.stop();
打破
}
}
}
公共无效写入(整数字节){
试一试{
mmOutStream.write(一个字节);
}捕获(IOE异常){
Log.e(“蓝牙服务”,“写入期间异常”,e);
}
}
公开作废取消(){
试一试{
mmSocket.close();
}捕获(IOE异常){
Log.e(“BluetoothService”,“连接套接字关闭()失败”,e);
}
}
}
sendArray是一个保持许多不同变量的单例

errorTilt、errorRoll和errorPan是从接收缓冲区更新的轴的当前值

“位置”保持位置标识字节的位置。它用于检查是否有任何变量已更新

很多时候,输入缓冲区只接收到一个字节,因为我不知道它应该是哪个轴,因为我没有关于它相对于位置字节的相对位置的信息,这个特定的字节是无用的,并且丢失了

我已经通过以下方法测试了接收的准确性。我让MCU在其中一个轴上输出一个三角波,而不是轴数据。在手机上,三角波的线条并不像人们想象的那样笔直,而是随机弯曲的,并含有人工制品

为了绘制数据,我使用GraphView,并从一个单独的线程以相等的间隔更新图形

我曾尝试使用更长的接收缓冲区(使用修改后的接收算法),但这没有帮助,因为一次只接收几个字节

我尝试过实现InputStream.available(),但它总是提供127个可用字节,这似乎不是真的

我读过很多关于类似问题的文章,在过去的5天里我一直在研究,但是我找不到一个好的解决方案

总之,我需要实现所有字节的准确、实时(或接近实时)接收

具有类似问题的线程:

多谢各位

更新:

我刚试过把信息发送出去
public void run() {
            byte[] bytes = new byte[38];
            int iterator = 0;
            while (true) {

                try {
                    int bytesAvailable = mmInStream.available();
                    if (bytesAvailable > 0) {
                        byte[] curBuf = new byte[bytesAvailable];
                        mmInStream.read(curBuf);
                        for (byte b : curBuf) {
                            if (b == (byte) 0xAA && iterator == 38) {
                                mHandler.obtainMessage(MainActivity.DATA_READ, bytes.length, -1, bytes).sendToTarget();
                                iterator = 0;
                                bytes[iterator] = b;
                            } else {
                                    bytes[iterator] = b;
                            }
                            iterator++;
                        }
                    }
                } catch (IOException ex) {
                    Log.e(TAG, "disconnected", ex);

                    connectionLost();
                    break;
                }
            }
}