Почему setCharacteristicNotification() фактически не включает уведомления?

BluetoothLeGatt Пример Android BLE содержит следующий код:

public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
                                          boolean enabled) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }
    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);

    // This is specific to Heart Rate Measurement.
    if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        mBluetoothGatt.writeDescriptor(descriptor);
    }
}

Мой вопрос в основном, почему отмеченный код относится к измерению сердечного ритма? Кажется, что наличие характеристики дескриптора конфигурации характеристики клиента (CCCD) является стандартным способом управления уведомлением о характеристике, так почему бы и нет setCharacteristicNotification() позаботиться о том, чтобы написать ему? И поскольку он этого не делает, что делает setCharacteristicNotification() на самом деле делать?

Я довольно новичок в BLE, и в интернете нет объяснений, которые не предполагают, что вы уже все поняли! Так что не думайте, что я знаю, что такое CCCD или что-то еще! Было достаточно сложно выяснить, что такое CCCD!

Изменить: см. Также этот ответ, который поддерживает мое понимание CCCD (и заставляет меня продолжать задаваться вопросом, почему вы должны писать на них вручную в Android, когда есть функция, которая выглядит так, как будто это должно сделать это для вас): https://devzone.nordicsemi.com/index.php/what-does-cccd-mean

6 ответов

Я думаю, что немного поздно для ответа, но сегодня у меня было то же самое сомнение, и я нашел четкий ответ. С помощью setCharacteristicNotification() Вы включаете локальное уведомление (на устройстве Android) и устанавливаете дескриптор CCC на ENABLE_NOTIFICATION_VALUE Вы включаете уведомления на периферийных устройствах. На самом деле для включения уведомления CCC вы должны использовать setValue() а также writeDescriptor() это методы, используемые для записи характеристик (в данном случае дескрипторов характеристик) на удаленное устройство. Я нашел это на: http://processors.wiki.ti.com/index.php/SensorTag_User_Guide

Вот выдержка из книги О'Рейли "Начало работы с Bluetooth с низким энергопотреблением":

Чтобы включить уведомления на Android, обычно необходимо локально включить уведомление для интересующей вас конкретной характеристики.

Как только это будет сделано, вы также должны включить уведомления на одноранговом устройстве, записав в дескриптор конфигурации характеристики клиента устройства (CCCD)

Я считаю, что это отвечает на ваш вопрос.

Так

mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); 

относится к первой части

а также

mBluetoothGatt.writeDescriptor(descriptor); 

относится ко 2-му.

Для будущих людей, сталкивающихся с этим, вот лучший ответ, который я мог найти:

Записывая в дескриптор Client Characteristic Config, вы, клиент, говорите серверу BLE переключать конфигурации. (Для меня это не имело никакого смысла, но на английском языке:)

Это говорит BLE-устройству переключать режимы (конфигурации), чтобы активно собирать и сообщать об изменениях этой характеристики вместо того, чтобы изменять и сообщать только по запросу.

Он плохо назван, но, просматривая документы, выясняется, что он также будет использоваться для других возможных изменений характеристик, которые клиент может запросить: отсюда и запутанное имя.

org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml

Напрашивается вопрос, зачем звонить BluetoothGatt.setCharacteristicNotification() если мы собираемся дублировать наши усилия, изменив дескриптор?! Копаться в BluetoothGatt Источник показывает нам, что setCharacteristicNotification подготавливает только локальную службу для получения уведомлений, а не для включения постоянных обновлений.

Я знаю, что это выглядит глупо, но установка значения CCCD - это единственный способ сообщить API, собираетесь ли вы включать уведомление или индикацию.

В настоящее время нет установленной характеристики. Чтобы включить индикацию, вы должны вызвать setCharacteristicNotification (сбивает с толку), а затем записать BluetoothGattDescriptor.ENABLE_INDICATION_VALUE в CCCD, аналогично тому, что вы сделали для включения уведомления.

Все остальные ответы на самом деле не отвечают на вопрос.

Я предполагаю, что команда Android BLE исходила из предположения, что приложение может иметь более одного BluetoothGattCallback().

Разделив включение (и отключение) уведомлений на два этапа, это позволит наблюдателям прослушивать уведомления ГАТТ (только вызывать setCharacteristicNotification()) - и оставить только один BluetoothGattCallbackреализация, выполняющая операции записи на сервер GATT, также известный как периферийное устройство BLE.

"Дескриптор конфигурации характеристики клиента определяет, как характеристика может быть настроена конкретным клиентом".

Другие вопросы по тегам