订阅通知后未调用BLE GATT onCharacteristicChanged [英] BLE GATT onCharacteristicChanged not called after subscribing to notification

查看:109
本文介绍了订阅通知后未调用BLE GATT onCharacteristicChanged的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我关于SO的第一篇文章.

this is my first post on SO.

在Android 5.0.2上订阅GATT通知时遇到一些问题.

I have some problems subscribing to GATT notifications on android 5.0.2 .

我打算做的是将具有BLE Shield的Arduino连接到我的Android手机.我有一个连接到Arduino的传感器,并希望通过使用BLE屏蔽将数据从Arduino发送到我的手机. 防护板上有一个nRF8001,它是服务器,我的手机/应用程序是客户端.

What I aim to do is to connect an Arduino with a BLE Shield to my Android phone. 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. There is a nRF8001 on the shield which is the server, my phone/app is the client.

我所做的是创建一个可扫描BLE设备的Android应用.它可以连接到设备并读取或写入特征.因此,我可以通过调用gatt.readCharacteristic(mCharacteristic);来手动"读取特征.这使我可以从Arduino获取传感器值. 我还使用nRFGo Studio创建了一个自定义服务.我知道这部分正在运行,因为我可以使用BLE扫描仪应用程序发现,连接甚至收到有关特性变化的通知,该应用程序可在Google Play上找到. 但是在我自己的应用程序中订阅通知将不起作用.好吧,至少可以进行订阅,但是永远不会调用onCharacteristicChanged(...).有趣的是,如果我在我的应用程序中订阅了该特征,然后又通过BLE扫描器应用程序 对其进行了订阅,则会突然调用onCharacteristicChanged(...),直到我再次通过BLE扫描器应用程序取消订阅. (我可以通过日志看到这一点)

What I did so far was to create an Android app which scans for BLE devices. It can connect to a device and read or write characteristics. So, I can "manually" read the characteristic by calling gatt.readCharacteristic(mCharacteristic);. This allows me to get the sensor values from the Arduino. I also created a custom Service by using 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. But subscribing to the notifications in my own app won't work. Well, at least the subscription works, but onCharacteristicChanged(...) is never called. 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. (I can see this by the Log)

我的Android代码如下: GATT回调:

My android code is as follows: The GATT callback:

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

这就是我连接到GATT的方式:

This is how I connect to GATT:

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

所有这些代码都在后台服务中运行,该服务在选择BLE设备后启动.

All of this code runs in a background service which is started after a BLE device is selected.

我尝试过的是实现类似于《 Google Dev API指南》中展示的功能,我也尝试过这种情况)或查看北欧开发人员地带在这种情况下确实有很大帮助.

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

最后,我的问题是:我做错了什么?我想念什么吗? 我只是想不通,现在快让我发疯了两天.我不知道我还能在哪里找到解决方案,所以希望您能为我提供帮助.

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全球分类:

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

编辑我在BLE扫描器中的工作: 我只是扫描BLE设备.它找到我的设备,点击它后,它会显示我在Arduino板上设置的所有服务.选择服务后,它将显示我为此服务指定的所有特性.当我点击一个特征时,它会向我显示其UUID和其服务的UUID.另外,BLE Scanner应用程序允许我订阅通知或阅读特征.当我订阅时,该值会不断更新.

EDIT What i do in BLE Scanner: I simply scan for BLE devices. It finds my device and after tapping on it it shows me all my services which I set up on the Arduino board. 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. Also, the BLE Scanner app allows me to subscribe to the notification or to read the characteristic. When I subscribe, the value is continously updated.

推荐答案

所以,我终于弄清楚了我的错误:) 正如您在上面看到的,我正在使用一个UUID,该UUID具有与我的特征相同的描述符基础(以3f54XXXX-....开头)

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

我将其更改为public static final UUID X_ACCEL_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");,现在一切正常.

I changed it to 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.

因此,我检查了RedBearLab Android应用程序示例,发现描述符的UUID等于发布在其他SO答案上的UUID.

So I checked the RedBearLab Android App example and saw that the descriptor's UUID equals the ones posted on other SO answers.

这也解释了为什么我的应用程序在BLE扫描仪应用程序中启用后收到通知的原因:由于描述符应在绑定设备的连接之间持久存在,因此BLE扫描仪应用程序也使用此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 GATT onCharacteristicChanged的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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