如何从字节数据读取蓝牙特性并将其转换为适当的值(用于抖动的蓝牙)

时间:2019-05-27 17:05:51

标签: flutter dart bluetooth

我必须读取和写入一些与Flutter一起使用的BLE(蓝牙低能耗)自行车智能教练的值。当我尝试从GATT特征org.bluetooth.characteristic.supported_power_range(位于bluetooth.org网站https://www.bluetooth.com/specifications/gatt/characteristics/中)读取值时,我得到了Int列表的返回值[0,0,200,0,1,0 ]。

GATT特性表示最小,最大和最大3个sint16字段。和步长瓦(功率)。

字节传输顺序还说,最低有效字节首先被传输。

我的猜测是,这3个参数以一个8位值的Int数组形式返回。但是我无法解释200的最大功率设置。因为智能教练应该提供最大2300W瓦电阻(ELITE Drivo https://www.elite-it.com/de/produkte/home-trainer/rollentrainer-interaktive/drivo

此代码段的输出结果:

device.readCharacteristic(savedCharacteristics[Characteristics.SUPPORTED_POWER_RANGE]).then((List<int> result) {
  result.forEach((i) {
    print(i.toString());
  });
});
// result: [0,0,200,0,1,0]

也许您中的某一个知道如何解释flutter_blue特征输出的二进制/十六进制/十进制值。 否则一些提示会很棒

3 个答案:

答案 0 :(得分:2)

连接Polar H10以恢复HR和RR间隔时,我遇到了同样的问题。可能不是100%一样,但是我认为我的情况可以指导您解决您的问题。

我收到与您喜欢的两个示例相同的列表:

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

GATT Bluetooth Heart Rate Service的规格来看,我发现检索到的列表的每个元素都与您所订阅的特征所传输的数据的1字节匹配。对于此服务,第一个字节,即列表的第一个元素,有一些标志指出在HR值之后(16)或不(0)是否有RR值。这只是根据标志值可能发生的许多不同情况中的两种情况,但是我认为这表明了第一个字节的重要性。

此后,HR值被编码为8位无符号整数(UINT8),即HR值与前面所示列表的第二个元素匹配。但是,RR间隔被编码为16位无符号整数(UINT16),因此它使列表#2 [16,61, 524,2 ]的后两个元素的转换变得复杂,因为我们应该使用16位来获取该值,并且字节顺序不正确。

这是我们导入库dart:typed_data

的时间
import 'dart:typed_data';

...

_parseHr(List<int> value) {

// First sort the values in the list to interpret correctly the bytes
List<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 list
var flags = valueSorted[0];

// Get the ByteBuffer view of the data to recode it later
var buffer = new Uint8List.fromList(valueSorted).buffer; // Buffer bytes from list

if (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);
}

希望这会有所帮助,关键是获取排序列表的缓冲区视图,获取所需的字节,并按标准指出的方式对它们进行重新编码。

答案 1 :(得分:2)

我使用了 print(new String.fromCharCodes(value));,这对我有用。

value 是您从 List<int> value = await characteristic.read();

回来的

感谢 ukBaz 对这个问题的回答。 Write data to BLE device and read its response flutter?

答案 2 :(得分:1)

这是一个很好的问题:

您可以使用我的软件包byte_data_wrapper将这些数据转换为您可以理解的十进制值:

  1. 获取缓冲区:
import 'dart:typed_data';

final buffer = Uint16List.fromList(result).buffer;
  1. 创建byteDataCreator:
// Don't forget to add it to your pubspec.yaml
//dependencies:
//  byte_data_wrapper:
//    git: git://github.com/Taym95/byte_data_wrapper.git

import 'byte_data_wrapper/byte_data_wrapper.dart';

final byteDataCreator = ByteDataCreator.view(buffer);
  1. 获取数据:
// You can use getUint8() if valeu is Uint8
final min = byteDataCreator.getUint16();
final max = byteDataCreator.getUint16();
final stepSize = byteDataCreator.getUint16();