Почему 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.
"Дескриптор конфигурации характеристики клиента определяет, как характеристика может быть настроена конкретным клиентом".