2

I am trying to write a little Zephyr OS runtime system that uses BLE to communicate between my two nrf52840dk boards. I have spent the past couple of days reading up on BLE and have gotten acquainted with GATT servers/clients.

The API I would preferably have looks something like this:

/* Send a message to conn */
void send(struct bt_conn *conn, void* data, u16_t len);

/* Callback which is invoked when a message is received from conn */
void recv(struct bt_conn *conn, void* data, u16_t len);

What I have managed to do is achieve something similar by limiting my system to two devices, one being a GATT server and one a GATT client.

The server exposes one attribute which the client scans for and subscribes to. The server can 'send' a message to the client by notifying it about a change to the attribute, and it can be sent messages by the client issuing a write request to the attribute.

The client can send messages to the server by writing to the attribute, while it can receive messages by the server notifying it of an update to the subscribed attribute.

I am thinking that primitives such as these ones must exist underneath the GATT layer (in the HCI layer?), but the Zephyr documentation is quite sparse at most places. Following this, I have two questions.

  • Is my understanding of BLE correct, that most communication between BLE devices happen through such GATT server/client relationships, or through BLE mesh networks?
  • Any pointers to information regarding where I can read up on writing the more generic API I described above (or if it already exists, pointers to that) would be helpful.

edit: I've accepted Youssifs answer. His answer together with the comments beneath it adequately answers my question.

Robert
  • 165
  • 10

1 Answers1

1

Is my understanding of BLE correct, that most communication between BLE devices happen through such GATT server/client relationships, or through BLE mesh networks?

You are correct in that most applications out there will be using the GATT server/client relationship. This is because when Bluetooth Low Energy was introduced in 2010 (and later launched with iPhone 4s through CoreBluetooth in 2011), this was the only method of communication. Since then, subsequent releases of BLE introduced newer methods of communication:-

  • LE L2CAP (introduced in BT v4.1, 2013) where lower level communication channels were used for fast and direct data transfer.
  • LE Mesh (introduced in 2017) where most of the communication is based on BLE adverts and therefore any device that is on v4.0 can theoretically support it.

The problems with both of these methods are the relative complexity and the slow adoption by vendors. As such, my recommendation is to continue using GATT examples/applications until you're more familiar with BLE and then proceed to using the other methods of communication.

Any pointers to information regarding where I can read up on writing the more generic API I described above (or if it already exists, pointers to that) would be helpful.

You've probably already seen this, but the Getting Started Gudie of Zephyr is quite useful. You can then use the Central HR example on one board and the Peripheral HR example on the other to get two way communication. Once this is done you can start customising your applications to match your needs. A list of all Bluetooth examples can be found here.

Below are further resources on BLE development in Zephyr:-

I hope this helps.

Youssif Saeed
  • 11,789
  • 4
  • 44
  • 72
  • Thanks for your reply! This is pretty much what I've done, modified the (central | peripheral)_hr examples. My main question is how the peripheral can send a message to an _individual_ client? Notifying subscribes of a change to an attribute will broadcast that notification. – Robert May 13 '20 at 11:12
  • Happy to help but not sure I understand your question then. It is the central that connects to a peripheral and enables notifications on a certain characteristic (e.g. Heart Rate Measurement characteristic). Then, every time there's a new HR reading or in certain intervals (this is application dependant) the peripheral would send new HR measurements to the connected central only (the new value is not broadcasted). This is a core part of the GATT level communication in Bluetooth. – Youssif Saeed May 14 '20 at 06:45
  • Sorry I was not clear when I phrased my question. Imagine that there are two clients connected to a peripheral, but the peripheral wishes to initiate and send a message to only _one_ of them. Effectively I would like to hack together a more general `send/recv` API, and find the GATT roles and their restrictions to be a little limiting. @Youssif Saeed – Robert May 14 '20 at 07:03
  • Ahh OK I understand now. Well in your scenario - with two centrals connected to one peripheral - if one central enables notifications on HRM measurement and the other doesn't then only the first central will receive the notifications. Even then, the peripheral can still choose not to send notifications to that central as you can modify the source accordingly. But you're right, GATT roles are limiting and for your use case I would recommend looking into BLE mesh as it is optimised for the publish/subscribe communication that you are referring to. – Youssif Saeed May 14 '20 at 08:12
  • Right now I am only using the subscription thing to hack together the ability to send messages from a peripheral which a client has not asked for. I am looking for one-to-one communication between servers and clients, where either the client or the server can initiate message transfer. @Youssif Saeed – Robert May 14 '20 at 08:24
  • Yes in this case you will not be able to use GATT roles because they rely on the GATT client being the initiator of all communication as you mentioned. – Youssif Saeed May 14 '20 at 09:48
  • Okay, thanks for the clarification! Would this be possible if we work on a lower layer in the BLE stack? @Youssif Saeed – Robert May 14 '20 at 13:33
  • I think it should be but it's not something that I have done before. As you mentioned, you can have a look at their HCI layer (https://docs.zephyrproject.org/latest/reference/bluetooth/hci_raw.html) or even better their L2CAP layer (https://docs.zephyrproject.org/latest/reference/bluetooth/l2cap.html) as more vendors support this. Seeing that you are using nordic hardware I recommend that you check out the nordic devzone if you haven't already as the nordic support team is very helpful and usually quick in their responses (https://devzone.nordicsemi.com/). – Youssif Saeed May 14 '20 at 14:54