Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Bluetooth LE - Read float characteristic

Tags:

I am trying to read the float characteristic of a connected Bluetooth LE device(Genuino 101). For testing purposes, the device provides a FloatCharacteristic with the hardcoded Value '55.3'. While I am able to receive a string that somehow resembles the float, I cannot read an actual float value.
Here's the code fragment that handles a string:

// For all other profiles, writes the data formatted in HEX.
        final byte[] data = characteristic.getValue();
        if (data != null && data.length > 0) {
            final StringBuilder stringBuilder = new StringBuilder(data.length);
            for(byte byteChar : data)
                stringBuilder.append(String.format("%02X ", byteChar));
            intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
        }

this is copied straight from the https://developer.android.com/samples/BluetoothLeGatt/index.html BLE demo project from the android developer homepage. The intent is then handled by this snippet:

private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        System.out.println("Broadcast received");
        final String action = intent.getAction();
        if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {

        } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {

        } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {

        } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
           displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
        }
    }
};

private void displayData(String data) {
    if (data != null) {
        System.out.println("Data Received: " + data);
    }
}

Which leads to the output

I/System.out: Data Received: 33]B 
I/System.out: 33 33 5D 42

So, set aside the swapped endianness, this is the correct hex value for 55.3f.
However, if I try to use characteristic.getFloatValue(), I only get garbage. Here's how I tried figuring out how to receive an actual float:

final byte[] data = characteristic.getValue();
        if (data != null && data.length > 0) {
            for (int i = 0; i< 333; i++) {
                try {
                    final float fData = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_FLOAT, i);
                    System.out.println("Offset = "+ i + ". Data that gets sent: " + fData + "/Data that we would expect: " + 55.3f);
                } catch (Exception e) {
                    System.out.println("Exception at offset " + i);
                }
            }
        }

the output is always

I/System.out: Offset = 0. Data that gets sent: Infinity/Data that we would expect: 55.3
I/System.out: Exception at offset 1
I/System.out: Exception at offset 2
...

What is my mistake here? Also, I'm not sure how the Offset parameter should be understood. Is it the offset in bit, in byte? Counting from MSB, from LSB? Also the documentation of getFloatValue() claims "returns float - Cached value of the characteristic at a given offset or null if the requested offset exceeds the value size. ". But the above snippet grossly exceeds the maximum size of any gatt characteristic, yet instead of returning 'null', the method call throws exceptions. So what's the correct way to get a float here?

like image 548
UnbescholtenerBuerger Avatar asked Feb 08 '17 13:02

UnbescholtenerBuerger


1 Answers

For the time being, I helped myself by formatting the data with

 float f1 = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).getFloa‌​t();

.

like image 176
UnbescholtenerBuerger Avatar answered Sep 21 '22 11:09

UnbescholtenerBuerger