简体   繁体   中英

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

I need to send a long (let's say 10Kb) notification from Bluez 5.37 on my Linux device to a mobile phone.

My implementation is based on src/shared/gatt-server.c .

I cannot find an example of this in Bluez. src/shared/gatt-server.c , bt_gatt_server_send_notification() is strictly trimming the packet to MTU-1 and discards the rest. I must need an output queue for this, like in gatt-client.c . bt_gatt_client_read_long_value() looks like an example of what I need, but for long characteristic reads.

  1. Is there a way to send a long notification compatible with majority of Bluetooth 4.0 Android phones? It requires a bit of collaboration on the phone side - sending a ATT_READ_BLOB_REQUESTS , AFAIS.
  2. Or is there a generic packetization library that will work over 20-byte-sized packets?
  3. Another way I can think of is to create another characteristic, use Notification messages for short messages and, er, notifications that "Hey, there's a long message, read it from that characteristic".

Which way is better? Does an example of any of the three ways exist?

I'm not entitled to disclose the code, but here's the basic idea of what I did. I use a tools/bgatt-server.c as an base for my peripheral.

To send a long message:

  • Save the notification_buffer being sent and the notification_position in the server 's fields;
  • Implement a bt_gatt_server_send_notification_with_callback() function in gatt-server.c . It should do the same as bt_gatt_server_send_notification() but have extra void *user_data and bt_gatt_server_destroy_func_t destroy arguments, and pass them to bt_att_send() . This will enqueue the next invocation of destroy callback when the bluez output queue becomes free.
  • Implement a bt_gatt_server_destroy_func_t that calculates the next chunk to be sent from server's notification_buffer and notification_position fields, send them with bt_gatt_server_send_notification_with_callback() and passes server as user_data and itself as the destroy callback.

To reassemble the message on receiving end:

  • I split the long message with my own packetizer/depacketizer.
  • I use a header: 1 byte - packet's messageId and 2 bytes for packetId - this way, one can have messages up to 17*65536 bytes length. Plus, this leaves the opportunity to re-request a packet for reliable delivery in the future.

I do this for 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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM