This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Designing BLE Characteristic Layout

Hi All,

I'm currently designing my implementation of BLE Services/Characteristics and wanted a quick review to make sure I'm on the right path based on my implementation. For example, here are my product requirements: (Note that this isn't exactly my requirements, but close enough for the purposes of discussions and my challenges)


  1. My device takes a temperature sample from 16 different temperature sensors each second and records the data to an EEPROM device.
  2. My device limit checks each temperature sensor and generates an "event" if a temperature goes out of limits. It records this event also to EEPROM. The event contains a timestamp, event number, temperature sensor number, temperature data, etc (Roughly 64 bytes)
  3. The device does the above 24/7, regardless of its BLE connection. There are no requirements to act differently when a temperature "event" occurs. It simply records that such an event happens.
  4. When a central BLE device (likely a smartphone app), connects, the phone should have the ability to interrogate the peripheral device and acquire:

Number of Events Occurred

Raw data for each event

Raw data from all temperature sensors that have been recorded


...I see this very similar to like a Fitbit. A Fitbit is recording a bunch of data all of the time (steps, HR, etc)... and then the phone app downloads all of this data when it's opened.

So, in terms of a BLE design, here are my current thoughts:

1 Service for my "Custom Temperature Logger"

  • UUID #1: Number of Events Recorded (read only)
  • UUID #2: Raw Data Command (read/write)
  • UUID #3: Raw Data Response (read/notify)

In this implementation, the smartphone app would read UUID #1 to determine that 3 events have been recorded. Then, I would implement some sort of command set where the phone would write into UUID #2 to send event data for event #1. Upon sending this command, the BLE device would start "streaming" notifications in UUID #3 with the raw data from the event until complete, and then set UUID #2 back to an "Idle" command. After which, the phone would then cycle through the other two events in the same fashion. I would have a similar command to read the 24/7 raw data from the device, where the device would just send a much larger data set, using the same architecture.

Is this appropriate? I ask since I want to make sure I'm not just implementing a "serial port" emulation and really using BLE characteristics appropriately. However, I cannot think of a more efficient way to structure my data, since each time my device will have a different number of temperature events logged, along with a different amount of raw 24/7 data.

In addition, in the BLE link layer, are notifications ACKed / retried if not ACKed correct? Or does one typically have to implement a way to ensure that all "streamed" data from continuous notifications are received correctly? I've found this thread and planning on using the basis of this to send my raw data: devzone.nordicsemi.com/.../

Thank you all in advance!! Let me know if you need more information!

  • Well. Yes, you are trying to use BLE (G)ATT in the right way and it looks good. Just note that if you really care about the throughput and delays caused by connecting procedures you might consider to implement simple one GATT Service + Characteristic "tube" and do all that data flow and commands/response protocol on higher layer. It can still be as elegant (defining some OP codes for selecting which event data you want and then receiving them in another structure) but of course it adds few bytes of overhead. But because typical GATT client cannot work with multiple handles and methods in one connection event it might not have any real impact on throughput and you will save 50-1000ms during connection (faster GATT Service discovery = each Service or Characteristic can take up to 300ms if your phone stack is "dumb" enough).

    To the reliability of lower layers and ack mechanism you can read some thoughts here and here.

  • Thanks, endnode and Emil!

    Emil -- Reading your link, it seems like the race condition is specifically trying to write at the same time that data is coming in. If I were to use a single characteristic for both reading and writing as endnode suggested, I would try to prevent that by having designated "ACK" and "End of Transfer" messages when multi-message transfers are used between the device and the host (essentially creating my own flow control).

    As long as the host software followed the flow control implementation, it looks like I wouldn't see the race condition you indicate. For my project, having a bit of overhead time / messages aren't a big deal. The sync via BLE will only happen 1 per day and if it's a few seconds longer than it needs to be, it won't matter.

    Thanks!

Related