Android BLE - 读取自定义服务

Posted

技术标签:

【中文标题】Android BLE - 读取自定义服务【英文标题】:Android BLE - read custom service 【发布时间】:2016-08-30 12:35:51 【问题描述】:

我尝试通过 BLE 通过 android 设备与 µ 控制器通信。我可以编写我的自定义特征(在我的开发套件上切换 LED),但无法读取 LED 状态的值('0x00' 表示关闭,'0x01' 表示开启)。

我想在单击某个项目时单击 ExpandableListView 时阅读它。目前我在 onChildClickListener 中实现了它。如果一个特征权限"PROPERTY_WRITE" > 0 那么它应该写入值。

private final ExpandableListView.OnChildClickListener servicesListClickListner =
            new ExpandableListView.OnChildClickListener() 
                @Override
                public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
                                            int childPosition, long id) 
                    if (mGattCharacteristics != null) 
                        final BluetoothGattCharacteristic characteristic =
                                mGattCharacteristics.get(groupPosition).get(childPosition);
                        final int charaProp = characteristic.getProperties();
                        if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) 
                            // If there is an active notification on a characteristic, clear
                            // it first so it doesn't update the data field on the user interface.
                            if (mNotifyCharacteristic != null) 
                                mBluetoothLeService.setCharacteristicNotification(
                                        mNotifyCharacteristic, false);
                                mNotifyCharacteristic = null;
                            
                            mBluetoothLeService.readCharacteristic(characteristic);
                        
                        if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) 
                            mNotifyCharacteristic = characteristic;
                            mBluetoothLeService.setCharacteristicNotification(
                                    characteristic, true);
                        

                        if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0)          

                            mBluetoothLeService.readCustomCharacteristic();
                            mBluetoothLeService.writeCustomCharacteristic(0x01);


                        
                        return true;
                    
                    return false;
                 

但它总是无法读取特征。 LED 值被写入,LED 切换到“ON”,但它不读取 LED 的值。 我想通过单击列表中的特性来读取打开/关闭 LED 的值。

我不知道我做错了什么。它应该读取特征,将其写入文本字段。在我的 BLE 设备上,我启用了阅读功能。我可以使用gatttool -> char-read-hnd [hnd] [val] 使用我的ubuntu 终端读取该值。

这是我在 mBluetoothLeService 中实现readCustomCharacteristic()

public void readCustomCharacteristic() 
        if (mBluetoothAdapter == null || mBluetoothGatt == null) 
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        
        /*check if the service is available on the device*/
        BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString("edfec62e-9910-0bac-5241-d8bda6932a2f"));
        if(mCustomService == null)
            Log.w(TAG, "Custom BLE Service not found");
            return;
        
        /*get the read characteristic from the service*/
        BluetoothGattCharacteristic mReadCharacteristic = mCustomService.getCharacteristic(UUID.fromString("18192021-2223-2425-2627-282930313233"));
        mBluetoothGatt.readCharacteristic(mReadCharacteristic);

        if(mBluetoothGatt.readCharacteristic(mReadCharacteristic) == false)
            Log.w(TAG, "Failed to read characteristic");
        
        return;
    

【问题讨论】:

为什么要执行两次mBluetoothGatt.readCharacteristic(mReadCharacteristic)? 在哪里执行两次?我执行它以执行,如果它成功在 logcat 中打印“读取特征失败”,我需要确认。有没有办法将状态保存在变量中?但是如果我读了两次它应该不会错。它应该只做两次并通过回调和广播更新方法更新我的数据。 mBluetoothGatt.readCharacteristic(mReadCharacteristic); if(mBluetoothGatt.readCharacteristic(mReadCharacteristic) == false) Log.w(TAG, "读取特征失败"); 您首先将它放在一行中,然后在 if 表达式中。 if 表达式可能总是会失败,因为一次只能有一个未完成的 GATT 操作。 “失败”是什么意思?它打印到日志中,所以据我了解,if 表达式工作正常。所以“false == false”..我怎样才能将状态放入变量中? 【参考方案1】:

看起来您可能缺少将描述符设置为通知/指示。我们必须手动执行此操作很痛苦(ios 不需要),但我想这些是我们提供的工具。这里有一个小sn-p可能会有所帮助:

BluetoothGattDescriptor descriptor = characteristic.getDescriptor(DESCRIPTOR_CONFIG_UUID);
bleGatt.setCharacteristicNotification(characteristic, true);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bleGatt.writeDescriptor(descriptor);

根据您的外围设备,您可能需要将描述符值设置为 ENABLE_INDICATION_VALUE。如果你不知道描述符 UUID,你可以这样做

characteristic.getDescriptors()

获取可用描述符的列表。

编写描述符后,您应该在 gatt 回调中调用 onDescriptorWrite。如果一切正常,并且未来的特征更改应该在您的 gatt 回调中调用 onCharacteristicChanged 方法。

希望这会有所帮助!

【讨论】:

你的说法是错误的。您必须在 BLE 设备上打开通知或指示才能使用它。 iOS 不会自动打开它,尽管设备可以通过固件设计将其打开。您提供的源代码示例中的toBeNotified 是什么? 感谢您的回答!在我的外围设备的代码中,我为我的服务设置了一个单独的 UUID,并为我的特性(128 位)设置了一个 UUID。我没有设置通知描述符或类似的东西。我使用了一个示例并按照我的设备制造商提供的教程进行操作,并且没有特征配置描述符。但我什至无法用描述符读出预定义的“自定义服务和特征”。这个字符的权限是读/写/写_no_response。来自安卓开发者的标准示例代码也不起作用。 我只知道一位同事告诉我的 iOS,如果我弄错了,请见谅。确实需要在固件级别启用它。不幸的是,Android 似乎并不关心它是否已经在硬件级别启用。我正在将我的代码转换为更通用的 sn-p,但我错过了那个变量。我已经修好了。 @Smokehead,这很有趣。当我遇到这个问题时,我正在使用一个内部硬件,我找不到描述符 UUID。所以,我做了一段特性.getDescriptors 代码。如果我是你,我会在你的第二个 sn-p 代码中插入 mReadCharacteristic.getDescriptors() 并打印出结果列表以查看可用的描述符。 如何打印它们..?这是一个List<BluetoothGattDescriptors> 我怎样才能打印出来或让它们在 logcat 中可见?

以上是关于Android BLE - 读取自定义服务的主要内容,如果未能解决你的问题,请参考以下文章

Android和双模蓝牙设备:与BR / EDR(经典)配对时未找到自定义BLE服务

android ble 自定义characteristic怎么解析

BLE4.0之自定义服务(CC2541)

ESP32学习笔记(30)——BLE GATT服务端自定义服务和特征

Android BLE GATT 外设模式通知

Android BLE 数据写入问题 - 出现错误 133