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?
For the time being, I helped myself by formatting the data with
float f1 = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).getFloat();
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With