Запись в несколько объектов BluetoothGatt на Android 4.4.4 Nexus 4

Я знаю, что это подробно обсуждалось, но я не нашел ответа, который бы решил проблему, с которой я столкнулся с Android Bluetooth LE.

Разработанная нами система позволяет подключаться к нескольким устройствам. Обнаружение и подключение к нескольким устройствам отлично работает. Каждый экземпляр объекта BluetoothGatt сохраняется на основе MAC-адреса устройства, и каждому из этих экземпляров назначается уникальный объект обратного вызова (это основано на информации с веб-сайта Nordic Semiconductor о подключениях нескольких устройств в Android).

Проблема возникает, когда я пытаюсь записать одни и те же данные на несколько устройств. Обычно каждая отдельная запись представляет собой одни и те же данные для одного и того же характеристического UUID, но в разных экземплярах BluetoothGatt. Все записи помещаются в очередь в приложении, чтобы гарантировать, что только один запрос записи ожидает в данный момент времени с помощью стека BT на Android. Я хорошо осведомлен об опасности поступить иначе, поскольку об этом имеется множество информации.

Я наблюдаю за тем, что одно из устройств, обычно первое, к которому я подключаюсь, всегда получает данные. Другие устройства никогда не получают данные. Однако стек BT возвращает onCharacteristicWrite для каждой отправляемой мной записи. Итак, стек BT, кажется, думает, что записал данные на все устройства, но вместо этого, кажется, ставит их в очередь. Если по прошествии некоторого времени (неизвестное количество времени) я отправляю команду только на одно из устройств, которое не получало данные, кажется, что стек BT отправляет все неотправленные данные на устройство, а затем любую команду, которую я последний раз отправлял как если ему была отправлена ​​команда flush (). Вот логарифм поведения:

11-18 01: 58: 55.571 E / testapp (1110): writeDataToCharacteristic (характеристика. Значение: [111, -1, 95])

11-18 01: 58: 55.571 D / testapp (1110): Характеристика WriteType: 1

11-18 01: 58: 55.571 I / testapp (1110): writeCharacteristic для CF: 9E: D0: 9A: 98: 90 со значением - [-1, -102, -112]

11-18 01: 58: 55.571 D / BluetoothGatt (1110): writeCharacteristic () - uuid: 9a143cb6-d775-4cfb-9eca-6e3a9b0f966b

11-18 01: 58: 55.571 D / BtGatt.GattService (1204): writeCharacteristic () - address = CF: 9E: D0: 9A: 98: 90

11-18 01: 58: 55.571 D / BtGatt.btif (1204): btif_gattc_write_char

11-18 01: 58: 55.571 D / BtGatt.btif (1204): btgattc_handle_event: Событие 1015

11-18 01: 58: 55.571 D / BtGatt.btif (1204): btif_gattc_upstreams_evt: Событие 4

11-18 01: 58: 55.571 D / BtGatt.GattService (1204): onWriteCharacteristic () - адрес = CF: 9E: D0: 9A: 98: 90, статус = 0

11-18 01: 58: 55.571 D / BluetoothGatt (1110): onCharacteristicWrite () - Device = CF: 9E: D0: 9A: 98: 90 UUID = 9a143cb6-d775-4cfb-9eca-6e3a9b0f966b Статус = 0

11-18 01: 58: 55.571 I / testapp (1110): onCharacterisiticWrite

11-18 01: 58: 55.571 E / testapp (1110): writeDataToCharacteristic (характеристика. Значение: [111, -1, 95])

11-18 01: 58: 55.581 D / testapp (1110): Характеристика WriteType: 1

11-18 01: 58: 55.581 I / testapp (1110): writeCharacteristic для DB: 7B: 3E: 47: AF: 1A со значением - [-1, -102, -112]

11-18 01: 58: 55.581 D / BluetoothGatt (1110): writeCharacteristic () - uuid: 9a143cb6-d775-4cfb-9eca-6e3a9b0f966b

11-18 01: 58: 55.581 D / BtGatt.GattService (1204): writeCharacteristic () - address = DB: 7B: 3E: 47: AF: 1A

11-18 01: 58: 55.581 D / BtGatt.btif (1204): btif_gattc_write_char

11-18 01: 58: 55.581 D / BtGatt.btif (1204): btgattc_handle_event: Событие 1015

11-18 01: 58: 55.581 D / BtGatt.btif (1204): btif_gattc_upstreams_evt: Событие 4

11-18 01: 58: 55.581 D / BtGatt.GattService (1204): onWriteCharacteristic () - address = DB: 7B: 3E: 47: AF: 1A, status = 0 Заявки на стек запись успешна, но данные никогда не поступают на устройство, и значение характеристики остается неизменным.

11-18 01: 58: 55.581 D / BluetoothGatt (1110): onCharacteristicWrite () - Устройство = DB: 7B: 3E: 47: AF: 1A UUID = 9a143cb6-d775-4cfb-9eca-6e3a9b0f966b Статус = 0

11-18 01: 58: 55.581 I / testapp (1110): onCharacterisiticWrite

В приведенном выше описании есть две характеристические записи в один и тот же характеристический UUID на двух разных устройствах. Основное отличие - это адрес устройства, который я выделил для ясности полужирным шрифтом. Стек утверждает, что выполнил обе записи, но на самом деле это не так. Я не нашел решения этой проблемы, так как кажется, что стек кэширует запись на второе устройство, но на самом деле не записывает ее. Обратите внимание, что у меня есть задержка между каждым набором записей, но каждая отдельная запись задерживается только из-за ожидания обратного вызова onCharacteristicWrite из стека.

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

if(canWrite) {
    for (BTDevice device : deviceList) {
        /* Each write is queued at a lower level. */
        device.sendData(data);
    }

    nextChangeAllowed = System.currentTimeMillis() + 100;
    canWrite = false;
}

if(nextChangeAllowed < System.currentTimeMillis()) {
    canWrite = true;
}

Кто-нибудь еще сталкивался с этой проблемой и решал ее?


person Eric Stutzenberger    schedule 17.11.2014    source источник
comment
Дополнительное тестирование с Samsung Galaxy S4 показывает, что код, который у меня есть, почти идеально работает на S4. По-прежнему ОЧЕНЬ мало случаев, когда данные не отправляются, но в целом проблема, кажется, исчезает. Итак, похоже, это может быть проблема Nexus 4.   -  person Eric Stutzenberger    schedule 18.11.2014
comment
У меня такая же проблема, когда я пытаюсь прочитать данные с двух устройств. Собственно подписываюсь на характеристики обоих устройств. Я получаю только один поток данных.   -  person DaviF    schedule 08.12.2014


Ответы (1)


Я столкнулся с такой же проблемой, как и ваша. Мне нужно было записать одну и ту же характеристику на два устройства, и я реализовал алгоритм, который записывал характеристику на второе устройство, только когда первое было записано и прочитано (когда был вызван onCharacteristicRead).

Таким образом, этот флаг canWrite (в вашем псевдокоде) должен быть изменен внутри обратного вызова onCharacteristicRead, когда предыдущая записанная характеристика была завершена, записана и прочитана.

Надеюсь это поможет.

person Álvaro Pérez Soria    schedule 18.11.2014
comment
Я не уверен, зачем было бы выполнять чтение после записи, учитывая, что метод onCharacteristicWrite показывает обновленное значение характеристики. Итак, в любом случае запись - это, по сути, чтение. Я попробую его на Nexus 4, чтобы посмотреть, есть ли разница. - person Eric Stutzenberger; 18.11.2014
comment
Кажется, что чтение после записи делает соединение еще более нестабильным, что опять же, поскольку все это основано на взаимодействии обратного вызова, это не имеет смысла. - person Eric Stutzenberger; 18.11.2014