How to read and convert Bluetooth characteristic from byte data to proper values(Bluetooth for flutter) How to read and convert Bluetooth characteristic from byte data to proper values(Bluetooth for flutter) dart dart

How to read and convert Bluetooth characteristic from byte data to proper values(Bluetooth for flutter)


I had the same problem connecting to a Polar H10 to recover HR and RR intervals. It might not be 100% the same, but I think my case can guide you to solve yours.

I am receiving the same list as you like these two examples:

  1. [0,60]
  2. [16,61,524,2]

Looking at the specs of the GATT Bluetooth Heart Rate Service I figured that each element of the list retrieved matches 1 byte of the data transmitted by the characteristic you are subscripted to. For this service, the first byte, i.e., the first element of the list, has some flags to point out if there is an RR value after the HR value (16) or not (0). This is just two cases among the many different ones that can ocur depending on the flags values, but I think it shows how important this first byte can be.

After that, the HR value is coded as an unsigned integer with 8 bits (UINT8), that is, the HR values match the second element of the lists shown before. However, the RR interval is coded as an unsigned integer eith 16bits (UINT16), so it complicates the translation of those two last elements of the list #2 [16,61,524,2], because we should use 16 bits to get this value and the bytes are not in the correct order.

This is when we import the library dart:typed_data

import 'dart:typed_data';..._parseHr(List<int> value) {// First sort the values in the list to interpret correctly the bytesList<int> valueSorted = [];valueSorted.insert(0, value[0]);valueSorted.insert(1, value[1]);for (var i=0; i< (value.length-3); i++) {  valueSorted.insert(i+2, value[i+3]);  valueSorted.insert(i+3, value[i+2]);}// Get flags directly from listvar flags = valueSorted[0];// Get the ByteBuffer view of the data to recode it latervar buffer = new Uint8List.fromList(valueSorted).buffer; // Buffer bytes from listif (flags == 0) {  // HR  var hrBuffer = new ByteData.view(buffer, 1, 1); // Get second byte  var hr = hrBuffer.getUint8(0);                  // Recode as UINT8  print(hr);}if (flags == 16) {  // HR  var hrBuffer = new ByteData.view(buffer, 1, 1); // Get second byte  var hr = hrBuffer.getUint8(0);                  // Recode as UINT8  // RR (more than one can be retrieved in the list)  var nRr = (valueSorted.length-2)/2; // Remove flags and hr from byte count; then split in two since RR is coded as UINT16  List<int> rrs = [];  for (var i = 0; i < nRr; i++) {    var rrBuffer = new ByteData.view(buffer, 2+(i*2), 2); // Get pairs of bytes counting since the 3rd byte    var rr = rrBuffer.getUint16(0);                       // Recode as UINT16    rrs.insert(i,rr);  }  print(rrs);}

Hope it helps, the key is to get the buffer view of the sorted list, get the bytes that you need, and recode them as the standard points out.


I used print(new String.fromCharCodes(value)); and that worked for me.

value is your return from List<int> value = await characteristic.read();

I thank ukBaz for his answer to this question. Write data to BLE device and read its response flutter?


You can use my package byte_data_wrapper to transform this data to a decimal value which you can understand:

  1. Get the buffer:
import 'dart:typed_data';final buffer = Uint16List.fromList(result).buffer;
  1. Create the byteDataCreator:
// Don't forget to add it to your pubspec.yaml//dependencies://  byte_data_wrapper://    git: git://github.com/Taym95/byte_data_wrapper.gitimport 'byte_data_wrapper/byte_data_wrapper.dart';final byteDataCreator = ByteDataCreator.view(buffer);
  1. Get your data :
// You can use getUint8() if valeu is Uint8final min = byteDataCreator.getUint16();final max = byteDataCreator.getUint16();final stepSize = byteDataCreator.getUint16();