例如,如何使用 Bluez 发送长通知?

How do I send a long notification with Bluez, example?

我需要从我的 Linux 设备上的 Bluez 5.37 向移动设备 phone.

发送一个长的(比如说 10Kb)通知

我的实现是基于src/shared/gatt-server.c.

我在 Bluez 中找不到这样的例子。 src/shared/gatt-server.cbt_gatt_server_send_notification() 严格将数据包修剪为 MTU-1,并丢弃其余部分。为此,我必须需要一个输出队列,例如 gatt-client.cbt_gatt_client_read_long_value() 看起来像我需要的例子,但对于长的特征读取。

  1. 有没有办法发送与大多数蓝牙 4.0 Android phones 兼容的长通知?它requires a bit of collaboration on the phone side - sending a ATT_READ_BLOB_REQUESTS, AFAIS.
  2. 或者是否有一个通用的打包库可以处理 20 字节大小的数据包?
  3. 我能想到的另一种方法是创建另一个特征,使用 Notification messages 作为短消息,呃,"Hey, there's a long message, read it from that characteristic".
  4. 的通知

哪种方式更好?是否存在这三种方式中的任何一种的示例?

我为 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);

我无权公开代码,但这是我所做工作的基本思路。我使用 tools/bgatt-server.c 作为外围设备的基础。

发送长消息:

  • 保存正在发送的 notification_bufferserver 字段中的 notification_position
  • gatt-server.c 中实现 bt_gatt_server_send_notification_with_callback() 函数。它应该与 bt_gatt_server_send_notification() 相同,但有额外的 void *user_databt_gatt_server_destroy_func_t destroy 参数,并将它们传递给 bt_att_send()。当 bluez 输出 queue 变为空闲时,这将启用 queue destroy 回调的下一次调用。
  • 实现一个 bt_gatt_server_destroy_func_t 计算下一个要从服务器的 notification_buffernotification_position 字段发送的块,用 bt_gatt_server_send_notification_with_callback() 发送它们并传递 server作为 user_data 和本身作为 destroy 回调。

要在接收端重组消息:

  • 我用自己的packetizer/depacketizer拆分了长消息。
  • 我使用 header:1 个字节 - 数据包的 messageId 和 2 个字节的 packetId - 这样,最多可以有 17*65536 字节长度的消息。另外,这也为将来 re-request 一个数据包的可靠交付留下了机会。