Как, например, отправить длинное уведомление с помощью Bluez?

Мне нужно отправить длинное (скажем, 10 КБ) уведомление от Bluez 5.37 на моем устройстве Linux на мобильный телефон.

Моя реализация основана на src/shared/gatt-server.c.

Я не могу найти такого примера в Bluez. src/shared/gatt-server.c, bt_gatt_server_send_notification() строго обрезает пакет до MTU-1 и отбрасывает остальное. Для этого мне нужна очередь вывода, как в gatt-client.c. bt_gatt_client_read_long_value() похоже на пример того, что мне нужно, но для длинных характерных чтений.

  1. Есть ли способ отправить длинное уведомление, совместимое с большинством телефонов Android с Bluetooth 4.0? Это требует некоторого взаимодействия со стороны телефона - отправки ATT_READ_BLOB_REQUESTS, AFAIS.
  2. Или существует общая библиотека пакетирования, которая будет работать с пакетами размером 20 байт?
  3. Другой способ, который я могу придумать, - это создать другую характеристику, использовать сообщения с уведомлениями для коротких сообщений и, э-э, уведомлений о том, что «Привет, есть длинное сообщение, прочтите его по этой характеристике».

Какой способ лучше? Существует ли пример любого из трех способов?


person Victor Sergienko    schedule 04.02.2016    source источник


Ответы (2)


Я не имею права раскрывать код, но вот основная идея того, что я сделал. Я использую tools / bgatt-server.c как база для моего периферийного устройства.

Чтобы отправить длинное сообщение:

  • Сохраните отправленный notification_buffer и notification_position в полях server;
  • Реализуйте функцию bt_gatt_server_send_notification_with_callback() в gatt-server.c. Он должен делать то же, что и bt_gatt_server_send_notification(), но иметь дополнительные аргументы void *user_data и bt_gatt_server_destroy_func_t destroy и передавать их bt_att_send(). Это приведет к следующему вызову обратного вызова destroy, когда очередь вывода bluez станет свободной.
  • Реализуйте bt_gatt_server_destroy_func_t, который вычисляет следующий фрагмент, который будет отправлен из полей notification_buffer и notification_position сервера, отправляет их с bt_gatt_server_send_notification_with_callback() и передает server как user_data и себя как destroy обратный вызов.

Чтобы собрать сообщение на принимающей стороне:

  • Я разделяю длинное сообщение с помощью моего собственного пакетировщика / депакетизатора.
  • Я использую заголовок: 1 байт - messageId пакета и 2 байта для packetId - таким образом, можно иметь сообщения длиной до 17 * 65536 байт. Кроме того, это оставляет возможность повторно запросить пакет для надежной доставки в будущем.
person Victor Sergienko    schedule 26.02.2016

Я делаю это для Bluez:

PRLOG("Send Notify, %d bytes\n", send_len);
do {
  if (RPService.valid) {
    send_res = bt_gatt_server_send_notification (pCharac->server->gatt, pCharac->handle,
                                                     pTx, mMIN(send_len, mBLE_TRANSFER_SIZE));
  } else {
    break;
  }
  if (send_res) {
    pTx += mBLE_TRANSFER_SIZE;
    send_len -= mBLE_TRANSFER_SIZE;
  } else {
    PRLOG("  Notify write failed...wait\n");
    usleep(mTX_WAIT);
  }
} while (send_len > 0);
person Cambsukguy    schedule 26.02.2016
comment
Спасибо! Другими словами, вы отправляете несколько уведомлений, и цепочка будет заблокирована, верно? Как долго вы отправляли данные? Вы пытались отправить уведомление 10k и одновременно получать сообщения? - person Victor Sergienko; 26.02.2016