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

查看:38
本文介绍了订阅通知后未调用 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 创建了一个自定义服务.我知道这部分正在工作,因为我能够通过使用 Google Play 上提供的 BLE Scanner 应用程序来发现、连接甚至收到有关特征变化的通知.但是在我自己的应用程序中订阅通知是行不通的.好吧,至少订阅有效,但是 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 指南中演示的内容,我也尝试过 这个解决方案(没有成功).既不在 Google 上搜索,也不在 SO 上阅读已经提出的问题(例如 这个 ) 或查看北欧开发者区在这种情况下确实有很大帮助.

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

编辑全局类:

// 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 与我的描述符具有相同的基础(以 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天全站免登陆