BLE NOTIFY 特性不通知

Posted

技术标签:

【中文标题】BLE NOTIFY 特性不通知【英文标题】:BLE NOTIFY characteristic not notifying 【发布时间】:2019-02-24 14:12:11 【问题描述】:

我需要与 BLE 温度计通信。工作流程是:

    注册关于 NOTIFY 特征的通知 在 WRITE 中写入初始化字符串,WRITE NO RESPONSE 特性 数据开始进入已注册的 NOTIFY 特征

这个过程在 Nordic nRF Connect 应用中完美运行。

但是,当我自己使用以下 BluetoothGattCallback 对象执行此操作时,它会失败 - 我永远不会得到更新 - onCharacteristicRead 或 onCharacteristicChanged 回调永远不会触发。不过,一切正常 - 所有应该在成功时返回 true 的方法都返回 true ......无论如何,这里是 BluetoothGattCallback:

private BluetoothGattCallback gattCallback = new BluetoothGattCallback() 
    /**
     * Callback indicating when GATT client has connected/disconnected to/from a remote
     * GATT server.
     *
     * @param gatt     GATT client
     * @param status   Status of the connect or disconnect operation.
     *                 @link BluetoothGatt#GATT_SUCCESS if the operation succeeds.
     * @param newState Returns the new connection state. Can be one of
     *                 @link BluetoothProfile#STATE_DISCONNECTED or
     *                 @link BluetoothProfile#STATE_CONNECTED
     */
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) 
        if (newState == BluetoothGatt.STATE_CONNECTED) 
            gatt.discoverServices();
         else 
            responseCharacteristic = null;
            isConnected = false;
            disconnected();
        
    

    /**
     * Callback invoked when the list of remote services, characteristics and descriptors
     * for the remote device have been updated, ie new services have been discovered.
     *
     * @param gatt   GATT client invoked @link BluetoothGatt#discoverServices
     * @param status @link BluetoothGatt#GATT_SUCCESS if the remote device
     */
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) 
        Log.wtf("THERMO", "Services discovered");
        BluetoothGattService thermoService = gatt.getService(THERMO_SERVICE);
        if (thermoService != null) 
            Log.wtf("THERMO", "Have service");
            //Find the characteristic
            configChar = thermoService.getCharacteristic(THERMO_CONFIGURATION);
            responseCharacteristic = thermoService.getCharacteristic(THERMO_RESPONSE);
            if (responseCharacteristic != null)
                setCharacteristicNotification(responseCharacteristic, true);
            else
                incompatibleTarget();
         else
            incompatibleTarget();
    

    /**
     * Callback triggered as a result of a remote characteristic notification.
     *
     * @param gatt           GATT client the characteristic is associated with
     * @param characteristic Characteristic that has been updated as a result
     */
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) 
        Log.wtf("THERMO", "onCharChanged");
        dataReceived(characteristic);
    

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) 
        Log.wtf("THERMO", "onCharRead");
        dataReceived(characteristic);
    

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) 
        Log.wtf("THERMO", "Write done");
        if (status == BluetoothGatt.GATT_SUCCESS) 
            Log.wtf("THERMO", "Write ok");
            if (responseCharacteristic != null) 
                Log.wtf("THERMO", "Have response");
                isConnected = true;
                connected();
            
         else 
        
    

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) 
        Log.wtf("THERMO", "onDescWrite");
        if (status == BluetoothGatt.GATT_SUCCESS) 
            if (configChar != null) 
                Log.wtf("THERMO", "Have config");
                configChar.setValue(thermoConfigData);
                Log.wtf("THERMO", "Writing: " + gatt.writeCharacteristic(configChar));
            
        
    
;

这里是注册通知的方法:

private void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) 
    gatt.setCharacteristicNotification(characteristic, enabled);
    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG);
    if (descriptor != null) 
        if (enabled) 
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
         else 
            descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        
        Log.wtf("THERMO", "notifyDesc: " + gatt.writeDescriptor(descriptor));
    

通知启用方法适用于所有其他设备。任何想法我做错了什么?

【问题讨论】:

gatt.setCharacteristicNotification(characteristic, enabled); 的结果是什么? 【参考方案1】:

出于某种原因,将回调代码更改为此有所帮助。看起来您需要在使用它们的回调中调用 getService 和 getCharacteristic,您不能将它们保存在变量中...

private BluetoothGattCallback gattCallback = new BluetoothGattCallback() 
    /**
     * Callback indicating when GATT client has connected/disconnected to/from a remote
     * GATT server.
     *
     * @param gatt     GATT client
     * @param status   Status of the connect or disconnect operation.
     *                 @link BluetoothGatt#GATT_SUCCESS if the operation succeeds.
     * @param newState Returns the new connection state. Can be one of
     *                 @link BluetoothProfile#STATE_DISCONNECTED or
     *                 @link BluetoothProfile#STATE_CONNECTED
     */
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) 
        if (newState == BluetoothGatt.STATE_CONNECTED) 
            gatt.discoverServices();
         else 
            responseCharacteristic = null;
            isConnected = false;
            disconnected();
        
    

    /**
     * Callback invoked when the list of remote services, characteristics and descriptors
     * for the remote device have been updated, ie new services have been discovered.
     *
     * @param gatt   GATT client invoked @link BluetoothGatt#discoverServices
     * @param status @link BluetoothGatt#GATT_SUCCESS if the remote device
     */
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) 
        Log.wtf("THERMO", "Services discovered");
        BluetoothGattService thermoService = gatt.getService(THERMO_SERVICE);
        if (thermoService != null) 
            Log.wtf("THERMO", "Have service");
            //Find the characteristic
            responseCharacteristic = thermoService.getCharacteristic(THERMO_RESPONSE);
            if (responseCharacteristic != null)
                setCharacteristicNotification(responseCharacteristic, true);
            else
                incompatibleTarget();
         else
            incompatibleTarget();
    

    /**
     * Callback triggered as a result of a remote characteristic notification.
     *
     * @param gatt           GATT client the characteristic is associated with
     * @param characteristic Characteristic that has been updated as a result
     */
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) 
        Log.wtf("THERMO", "onCharChanged");
        dataReceived(characteristic);
    

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) 
        Log.wtf("THERMO", "onCharRead");
        dataReceived(characteristic);
    

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) 
        Log.wtf("THERMO", "Write done");
        if (status == BluetoothGatt.GATT_SUCCESS) 
            Log.wtf("THERMO", "Write ok");
            if (responseCharacteristic != null) 
                Log.wtf("THERMO", "Have response");
                isConnected = true;
                connected();
            
         else 
        
    

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) 
        Log.wtf("THERMO", "onDescWrite");
        if (status == BluetoothGatt.GATT_SUCCESS) 
            BluetoothGattService thermoService = gatt.getService(THERMO_SERVICE);
            if (thermoService != null) 
                configChar = thermoService.getCharacteristic(THERMO_CONFIGURATION);
                if (configChar != null) 
                    Log.wtf("THERMO", "Have config");
                    configChar.setValue(thermoConfigData);
                    Log.wtf("THERMO", "Writing: " + gatt.writeCharacteristic(configChar));
                
            
        
    
;

【讨论】:

以上是关于BLE NOTIFY 特性不通知的主要内容,如果未能解决你的问题,请参考以下文章

Android BLE 无法从设备接收 Gatt 特性通知

低功耗蓝牙通知特性

Android BLE GATT 外设模式通知

BLE Android,不能启用超过 1 个关于读取特性的通知

BLE通信数据类型

Android BLE 4.3 onDescriptorWrite 在启用特征通知时返回状态 128