akexorcist / BluetoothSPPLibrary

[UNMAINTAINED][Android] Bluetooth Serial Port Profile which comfortable to developer application to communication with microcontroller via bluetooth
Apache License 2.0
1.7k stars 572 forks source link

Prematurely terminating data packets with byte values of 10 (LF) and 13 (CR) #83

Closed phillip-toone closed 7 years ago

phillip-toone commented 7 years ago

I've come across a possible limitation with this library and I look forward to hearing what input others may have regarding it. I would like to communicate 4 byte integers from an arduino to an Android device as fast as possible. In order to do this I send the integer through the bluetooth device one byte at a time like this:

long x = 266;
Serial.write(x & 0xFF);
Serial.write((x >> 8) & 0xFF);
Serial.write((x >> 16) & 0xFF);
Serial.write((x >> 24) & 0xFF);
Serial.println();

I receive these four bytes and combine them as follows:

bt.setOnDataReceivedListener(new BluetoothSPP.OnDataReceivedListener() {
    public void onDataReceived(byte[] data, String message) {
        int value;
        value = ((data[0] << 0) & 0xFF) + ((data[1] << 8) & 0xFFFF) + ((data[2] << 16) & 0xFFFFFF) + ((data[3] << 24) & 0xFFFFFF);
    }
});

This works great until one of the four bytes happen to be a 10 (LF) or a 13 (CR). This prematurely terminates the data packet and crashes the android application since the remaining bytes are out of range. I could simply check the length of the array to avoid crashing the application but I don't want to have to disregard every value containing one of these two characters because that data may be critical to operation. I'm looking forward to hearing any thoughts, suggestions or recommendation that any of you may have. Thanks in advance. :)

phillip-toone commented 7 years ago

I realize that this isn't really and "error" in the code but rather my attempt to use it in a way that is was never intended. If anyone can give me any advice on how I can modify the code to be used in the way I desire I would really appreciate it. Thanks.

phillip-toone commented 7 years ago

Here is the solution I am using to deal with this issue. I have copied and pasted the library into my project so that I can modify the BluetoothService.java file. An integer called bytesLeft is used to count down the number of bytes that should pass through the if statement used to look for a carriage return and line feed. In the following example I use the ASCII character '*' as the first byte to communicate that the following 7 bytes are to be exempt from this if statement.

public void run() {
    byte[] buffer;
    ArrayList<Integer> arr_byte = new ArrayList<Integer>();
    int bytesLeft = 0;
    // Keep listening to the InputStream while connected
    while (true) {
        try {
            int data = mmInStream.read();
            if (data == '*' && arr_byte.size() == 0) bytesLeft = 8;
            if (data == 0x0A && bytesLeft == 0) {
            } else if(data == 0x0D && bytesLeft == 0) {
                buffer = new byte[arr_byte.size()];
                for(int i = 0 ; i < arr_byte.size() ; i++) {
                    buffer[i] = arr_byte.get(i).byteValue();
                }
                // Send the obtained bytes to the UI Activity
                mHandler.obtainMessage(BluetoothState.MESSAGE_READ
                        , buffer.length, -1, buffer).sendToTarget();
                arr_byte = new ArrayList<Integer>();
            } else {
                arr_byte.add(data);
                if (bytesLeft != 0) bytesLeft = bytesLeft - 1;
            }
        } catch (IOException e) {
            connectionLost();
            // Start the service over to restart listening mode
            BluetoothService.this.start(BluetoothService.this.isAndroid);
            break;
        }
    }
}