Android 蓝牙 LE - 读取浮动特性

Posted

技术标签:

【中文标题】Android 蓝牙 LE - 读取浮动特性【英文标题】:Android Bluetooth LE - Read float characteristic 【发布时间】:2017-02-08 13:05:23 【问题描述】:

我正在尝试读取连接的蓝牙 LE 设备 (Genuino 101) 的浮动特性。出于测试目的,该设备提供了一个带有硬编码值“55.3”的 FloatCharacteristic。虽然我能够接收到一个类似于浮点数的字符串,但我无法读取实际的浮点值。 这是处理字符串的代码片段:

// 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());
        

这是直接从 android 开发者主页上的https://developer.android.com/samples/BluetoothLeGatt/index.html BLE 演示项目复制而来的。 然后由这个 sn-p 处理意图:

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

导致输出

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

所以,抛开交换的字节顺序,这是 55.3f 的正确十六进制值。 但是,如果我尝试使用特性.getFloatValue(),我只会得到垃圾。以下是我尝试弄清楚如何接收实际浮点数的方法:

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

输出总是

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
...

我的错误是什么?另外,我不确定应该如何理解 Offset 参数。它是以位为单位的偏移量,以字节为单位吗?从 MSB 算起,从 LSB 算起? getFloatValue() 的文档还声称“返回浮点数 - 如果请求的偏移量超过值大小,则返回给定偏移量处特征的缓存值或 null。”。但是上面的 sn-p 大大超过了任何 gatt 特征的最大大小,但是方法调用不是返回“null”,而是抛出异常。 那么在这里获得浮点数的正确方法是什么?

【问题讨论】:

目前,我通过使用float f1 = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).getFloat(); 格式化数据来帮助自己,尽管这是一个“快速而肮脏的黑客”,我宁愿使用专用的 getFloatValue() 方法。 如果您尝试将一个字节解析为 int ? 您在 i 上循环,但每次循环都会得到相同的值,因为特性中的偏移量(BluetoothGattCharacteristic.FORMAT_FLOAT, 0) 始终设置为 0。尝试将其设置为“我”代替。 感谢@Nebr 指出,这个错误确实漏掉了。但它并没有解决我的问题,我相应地更新了我的问题。 @Daniel ,不知道你在那里建议什么。你的意思是 BluetoothGattCharacteristic.getIntValue() 方法?这听起来像是更糟糕的黑客攻击。 【参考方案1】:

暂时,我通过使用

格式化数据来帮助自己
 float f1 = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).getFloa‌​t();

.

【讨论】:

以上是关于Android 蓝牙 LE - 读取浮动特性的主要内容,如果未能解决你的问题,请参考以下文章

将数据写入 Android 中的蓝牙 LE 特性

Android 蓝牙 LE 通知的问题

Android蓝牙LE:连接后未发现服务

Android 蓝牙 LE 外设 IP 是静态的吗?

蓝牙扫描功能

用于读取测量数据的蓝牙 LE 配置文件