简体   繁体   English

BLE GATT onCharacteristicChanged在订阅通知后没有调用

[英]BLE GATT onCharacteristicChanged not called after subscribing to notification

this is my first post on SO. 这是我关于SO的第一篇文章。

I have some problems subscribing to GATT notifications on android 5.0.2 . 我在Android 5.0.2上订阅GATT通知时遇到了一些问题。

What I aim to do is to connect an Arduino with a BLE Shield to my Android phone. 我的目的是将Arduino和BLE Shield连接到我的Android手机。 I have a sensor connected to the Arduino and want to send the data from the Arduino to my phone by using the BLE shield. 我有一个连接到Arduino的传感器,想要使用BLE屏蔽将数据从Arduino发送到我的手机。 There is a nRF8001 on the shield which is the server, my phone/app is the client. 盾牌上有一个nRF8001是服务器,我的手机/应用程序是客户端。

What I did so far was to create an Android app which scans for BLE devices. 到目前为止我所做的是创建一个扫描BLE设备的Android应用程序。 It can connect to a device and read or write characteristics. 它可以连接到设备并读取或写入特征。 So, I can "manually" read the characteristic by calling gatt.readCharacteristic(mCharacteristic); 所以,我可以通过调用gatt.readCharacteristic(mCharacteristic);来“手动”读取特性gatt.readCharacteristic(mCharacteristic); . This allows me to get the sensor values from the Arduino. 这允许我从Arduino获取传感器值。 I also created a custom Service by using nRFGo Studio. 我还使用nRFGo Studio创建了一个自定义服务。 I know that this part is working as I am able to discover, connect and even to be notified about changes of the characteristic by using the BLE Scanner app which is available on Google Play. 我知道这部分工作正常,因为我可以使用Google Play上提供的BLE扫描仪应用程序发现,连接甚至收到有关特征变化的通知。 But subscribing to the notifications in my own app won't work. 但订阅我自己的应用程序中的通知将无法正常工作。 Well, at least the subscription works, but onCharacteristicChanged(...) is never called. 好吧,至少订阅有效,但onCharacteristicChanged(...)永远不会被调用。 What's funny is the fact that if I subscribe to the characteristic in my app and afterwards subscribe to it with the BLE scanner app suddenly onCharacteristicChanged(...) is called until I unsubscribe again through the BLE scanner app. 有趣的是,如果我订阅我的应用程序中的特性, 然后突然在BLE扫描仪应用程序上订阅它,则会调用onCharacteristicChanged(...) ,直到我再次通过BLE扫描仪应用程序取消订阅。 (I can see this by the Log) (我可以通过Log看到这个)

My android code is as follows: The GATT callback: 我的android代码如下:GATT回调:

private final BluetoothGattCallback mGattCallback =
        new BluetoothGattCallback() {
            @Override
            public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                                int newState) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    sendBroadcastConnected();

                    Log.i("BLE", "Connected to GATT server.");
                    Log.i("BLE", "Attempting to start service discovery:" + bleManager.startServiceDiscovery());

                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    sendBroadcastDisconnected();
                    Log.i("BLE", "Disconnected from GATT server.");
                }
            }

            @Override
            public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    Log.w("BLE", "onServicesDiscovered ");
                    setNotifySensor(gatt);     
                }
            }

            private void setNotifySensor(BluetoothGatt gatt) {
                BluetoothGattCharacteristic characteristic = gatt.getService(Globals.MPU_SERVICE_UUID).getCharacteristic(Globals.X_ACCEL_CHARACTERISTICS_UUID);
                gatt.setCharacteristicNotification(characteristic, true);

                BluetoothGattDescriptor desc = characteristic.getDescriptor(Globals.X_ACCEL_DESCRIPTOR_UUID);
                Log.i("BLE", "Descriptor is " + desc); // this is not null
                desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                Log.i("BLE", "Descriptor write: " + gatt.writeDescriptor(desc)); // returns true

            }

            @Override
            public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                               if(Globals.X_ACCEL_CHARACTERISTICS_UUID.equals(characteristic.getUuid())){
                    Log.w("BLE", "CharacteristicRead - xaccel service uuid: " + characteristic.getService().getUuid());
                    Log.w("BLE", "CharacteristicRead - xaccel value: " + characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8,0));
                }
            }

            @Override
            public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
                Log.i("BLE", "Received characteristics changed event : "+characteristic.getUuid());
                if(Globals.X_ACCEL_CHARACTERISTICS_UUID.equals(characteristic.getUuid())){
                    Log.i("BLE", "Received new value for xAccel.");
                }


            }

            @Override
            public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            }

            @Override
            public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            }

            @Override
            public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            }
        };

This is how I connect to GATT: 这就是我连接GATT的方式:

        bt_device = createBluetoothDevice(DEVICE_ADRESS);
        BluetoothGatt mBluetoothGatt = bt_device.connectGatt(context, false, mGattCallback);

All of this code runs in a background service which is started after a BLE device is selected. 所有这些代码都在后台服务中运行,后台服务在选择BLE设备后启动。

What I tried was to implement things like they are demonstrated in the Google Dev API Guide and I also tried this solution (without success). 我尝试的是实现Google Dev API指南中演示的内容,我也试过这个解决方案 (没有成功)。 Neither searching on Google, reading questions already asked on SO (For example this one ) or having a look on the Nordic Developer Zone did help much in this case. 既没有在谷歌上搜索,也没有在SO(例如这个 )上阅读问题或者看过北欧开发者专区,这在这种情况下确实有很大帮助。

Finally, my question is: What have I done wrong? 最后, 我的问题是:我做错了什么? Am I missing something? 我错过了什么吗? I just can't figure it out and it's driving me crazy for two days now. 我只是无法理解它现在让我疯狂了两天。 I don't know where else I could search for a solution, so I hope you can help me.. 我不知道我还能在哪里寻找解决方案,所以我希望你能帮助我..

EDIT Globals Class: 编辑全球类:

// BLE Services
public static final UUID MPU_SERVICE_UUID = UUID.fromString("3f540001-1ee0-4245-a7ef-35885ccae141");
// BLE Characteristics
public static final UUID X_ACCEL_CHARACTERISTICS_UUID = UUID.fromString("3f540002-1ee0-4245-a7ef-35885ccae141");
// BLE Descriptors
public static final UUID X_ACCEL_DESCRIPTOR_UUID = UUID.fromString("3f542902-1ee0-4245-a7ef-35885ccae141");

EDIT What i do in BLE Scanner: I simply scan for BLE devices. 编辑我在BLE扫描仪中做的事情:我只是扫描BLE设备。 It finds my device and after tapping on it it shows me all my services which I set up on the Arduino board. 它找到了我的设备并在点击它之后向我展示了我在Arduino板上设置的所有服务。 After selecting a service it shows me all my chatacteristics which I specified for this Service. 选择服务后,它会显示我为此服务指定的所有聊天功能。 And when I tap on a characteristic, it shows me its UUID and its Service's UUID. 当我点击一个特征时,它会显示它的UUID及其服务的UUID。 Also, the BLE Scanner app allows me to subscribe to the notification or to read the characteristic. 此外,BLE扫描仪应用程序允许我订阅通知或阅读特征。 When I subscribe, the value is continously updated. 订阅时,该值会不断更新。

So, I finnally figured out my mistake :) As you can see above, I'm usinng a UUID with the same base for my descriptor as my characteristics (starting with 3f54XXXX-.... ) 所以,我最终弄清楚了我的错误:)正如你在上面看到的那样,我使用的UUID与我的描述符具有相同的基础作为我的特征(从3f54XXXX-....开始)

I changed it to public static final UUID X_ACCEL_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); 我将其更改为public static final UUID X_ACCEL_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); and now everything is working as expected. 现在一切都按预期工作了。

I did not do this before as i thought that there should be a descriptor for each characteristic. 之前我没有这样做,因为我认为应该有每个特征的描述符。 But in fact, according to the Client Characteristic Configuration the ... 但实际上,根据客户端特性配置 ...

[...] descriptor shall be persistent across connections for bonded devices. [...]描述符应在绑定设备的连接上保持不变。 The Client Characteristic Configuration descriptor is unique for each client. 客户端特征配置描述符对于每个客户端是唯一的。

So I checked the RedBearLab Android App example and saw that the descriptor's UUID equals the ones posted on other SO answers. 所以我查看了RedBearLab Android App示例,发现描述符的UUID等于其他SO答案上发布的UUID。

This also explains why my App received Notifications after I enabled them in the BLE Scanner App: As the descriptor shall be persistent across connections for bonded devices, the BLE Scanner App used also this UUID for the descriptor and thus enabled notifications for the client (= my phone). 这也解释了为什么我的应用程序在BLE扫描仪应用程序中启用后会收到通知:由于描述符应在绑定设备的连接上保持不变,因此BLE扫描程序应用程序也使用此UUID作为描述符,从而为客户端启用通知(=我的手机)。

customBluetoothGatt.setCharacteristicNotification(characteristic, enabled); customBluetoothGatt.setCharacteristicNotification(特性,已启用);

    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
    boolean success = customBluetoothGatt.writeDescriptor(descriptor);

Now set the descriptor property ENABLE_INDICATION_VALUE 现在设置描述符属性ENABLE_INDICATION_VALUE

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM