如何读取蓝牙特性并将其从字节数据转换为适当的值(用于抖动的蓝牙) [英] How to read and convert Bluetooth characteristic from byte data to proper values(Bluetooth for flutter)

查看:67
本文介绍了如何读取蓝牙特性并将其从字节数据转换为适当的值(用于抖动的蓝牙)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须读取和写入一些与Flutter一起使用的BLE(蓝牙低功耗)自行车智能教练的值.当我尝试从GATT特征org.bluetooth.characteristic.supported_power_range(位于bluetooth.org网站

我还得到了支持的功率水平的返回值,为[0,0,160,15,1,0].现在的解决方案是如何读取2个字节的最大功率级别:您将获得160,15规格的LSO(首先是最低有效八位位组,请不要将其与LSB最低有效位相混淆).实际上,您必须像15160一样阅读它.现在使用第一个字节 15 * 256 + 160 = 4000 进行数学运算,这就是培训师正确的最大支持功率,如数据表中所示.

我希望我能帮助别人.感谢您的两次回复,它们也都是正确的,并帮助我发现了错误.

解决方案

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

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

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

看看 GATT蓝牙心率服务的规范,我发现每个元素检索到的列表中的1个与您所订阅的特征所传输的数据的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>值){//首先对列表中的值进行排序以正确解释字节List< int>valueSorted = [];valueSorted.insert(0,value [0]);valueSorted.insert(1,value [1]);对于(var i = 0; i<(value.length-3); i ++){valueSorted.insert(i + 2,value [i + 3]);valueSorted.insert(i + 3,value [i + 2]);}//直接从列表中获取标志var标志= valueSorted [0];//获取数据的ByteBuffer视图以供以后重新编码var buffer = new Uint8List.fromList(valueSorted).buffer;//列表中的缓冲区字节如果(标志== 0){//人力资源var hrBuffer = new ByteData.view(buffer,1,1);//获取第二个字节var hr = hrBuffer.getUint8(0);//重新编码为UINT8打印(小时);}如果(标志== 16){//人力资源var hrBuffer = new ByteData.view(buffer,1,1);//获取第二个字节var hr = hrBuffer.getUint8(0);//重新编码为UINT8//RR(列表中可以检索到多个)var nRr =(valueSorted.length-2)/2;//从字节数中删除标志和hr;然后分成两部分,因为RR编码为UINT16List< int>rrs = [];对于(var i = 0; i< nRr; i ++){var rrBuffer = new ByteData.view(buffer,2+(i * 2),2);//获取从第三个字节开始计数的成对字节var rr = rrBuffer.getUint16(0);//重新编码为UINT16rrs.insert(i,rr);}打印(rrs);} 

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

I have to read and write some values to a Bike Smart trainer with BLE (Bluetooth Low Energy) used with Flutter. When I try to read the values from the GATT characteristic org.bluetooth.characteristic.supported_power_range (found on bluetooth.org site https://www.bluetooth.com/specifications/gatt/characteristics/ ) I get the return value of an Int List [0,0,200,0,1,0].

The GATT characteristic sais that there are 3 sint16 fields for Min., Max. and step size Watts (Power).

The Byte transmission order also sais that the least significant octet is transmitted first.

My guessings are, that the 3 parameters are returned in an Int array with 8bit value each. But I can't interpret the 200 for maybe the maximum Power setting. Because the smart trainer should provide max. 2300W Watts resistance (ELITE Drivo https://www.elite-it.com/de/produkte/home-trainer/rollentrainer-interaktive/drivo)

The Output results from this code snippet:

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

Maybe some one of u knows how to interpret the binary/hex/dec values of the flutter_blue characteristic output. Or some hints would be great

Edit

For future readers, I got the solution. I'm a bit asheamed because I read the wrong characteristic.

The return value [0,0,200,0,1,0] was for supported resistance level. (which is 20% and the 200 shows the 20% with a resolution of 0.1 like described in the GATT spec)

I also got a return value for the supported power level which was [0,0,160,15,1,0]. Now the solution how to read the 2 Bytes of max powre level: you get the 160,15 the spec sais LSO (least significant octet first, don't confuse it with LSB least significant bit first). In fact of that you have to read it like 15,160. now do the math with the first Byte 15*256 + 160 = 4000 and thats the correct maximum supported power of the trainer like in the datasheet.

I hope I help someone with that. Thanks for the two replys they are also correct and helped me to find my mistake.

解决方案

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

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.

这篇关于如何读取蓝牙特性并将其从字节数据转换为适当的值(用于抖动的蓝牙)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆