Bluetooth Low Energy

What are GATT services and characteristics?

GATT, the Generic Attribute Profile, is the structure Bluetooth Low Energy devices use to expose data once connected. A device's data is grouped into services, each service holds characteristics, and each characteristic is a single value with properties that say whether it can be read, written or subscribed to. Every service and characteristic is identified by a UUID.

Learning objectives

After reading this article you will be able to:

  • Describe the GATT hierarchy of profiles, services, characteristics and descriptors
  • Distinguish SIG-registered 16-bit UUIDs from the custom 128-bit UUIDs apps generate
  • Explain how a client reads, writes and subscribes to characteristic values

What GATT is for

After two Bluetooth Low Energy devices connect, they need a shared way to say what data exists and how to reach it. The Generic Attribute Profile (GATT) provides it. The Core Specification describes GATT as the structure in which profile data is exchanged, built on top of the Attribute Protocol (ATT). Android’s BLE overview puts it more plainly: GATT is a general specification for sending and receiving short pieces of data, known as attributes, over a BLE link.

GATT has two roles. The server holds the data and answers requests. The client sends requests and receives responses, notifications and indications. The specification notes that these roles are not fixed to a device: a device takes a role when it starts a procedure, and it can act as client and server at the same time. In the common case, a sensor is the server and the phone reading it is the client.

The hierarchy: profiles, services, characteristics

GATT organises data in layers.

  • Profile. The top level. A profile is one or more services that together fulfil a use case, such as a heart rate monitor.
  • Service. A collection of data and behaviours for one function or feature of the device. A service can be primary, exposing functionality of the device, or secondary, meant only to be included by another service.
  • Characteristic. A single value used in a service, along with properties that say how the value can be accessed. Android’s overview compares a characteristic to a type, like a class.
  • Descriptor. Extra information about a characteristic value, such as a human-readable description, a valid range or a unit of measure. A characteristic can have none or several.

Apple’s Core Bluetooth guide gives a concrete example. A heart rate monitor has a heart rate service. Inside it, one characteristic holds the body location of the sensor and another carries the heart rate measurements.

How everything is identified

Every service, characteristic and descriptor has a type, given as a UUID. The Bluetooth SIG registers short 16-bit UUIDs for standard ones in its Assigned Numbers. The Heart Rate service is 0x180D, the Heart Rate Measurement characteristic is 0x2A37, and the Client Characteristic Configuration descriptor is 0x2902.

These short forms stand in for full 128-bit UUIDs. Apple’s guide explains that 180D is shortened from 0000180D-0000-1000-8000-00805F9B34FB, built on the Bluetooth base UUID. A custom service, one the SIG has not defined, uses a 128-bit UUID that the developer generates. This is how two copies of an app recognise each other: both are built with the same custom service and characteristic UUIDs, and one device can look for that service in advertising packets before it connects.

Underneath, the Attribute Protocol stores each of these items as an attribute with a type, a 16-bit handle that the server assigns, and permissions. Clients discover the handles, then use them in read and write requests. Apps rarely see handles directly; platform APIs work with service and characteristic objects.

Reading, writing and subscribing

A characteristic’s properties decide what a client may do with it:

  • Read. The client asks for the current value.
  • Write. The client sends a new value. A write request gets a response from the server. A write command, called write without response on iOS and Android, does not, so the client gets no confirmation.
  • Notify and indicate. The server pushes the value whenever it changes. To turn this on, the client writes to the characteristic’s Client Characteristic Configuration descriptor. Android’s guide shows this step: enable notifications locally, then write the descriptor on the remote device.

On the server side, Core Bluetooth sends updates with updateValue(_:for:onSubscribedCentrals:), and Android uses BluetoothGattServer.

A typical session after connecting runs in this order: discover services, discover the characteristics in the service you need, subscribe to the ones that change, and read or write the rest.

Size limits

Values are small. The Attribute Protocol limits an attribute value to 512 octets, and a single packet carries less than that, depending on the ATT MTU the two devices agree. Longer values need special read and write procedures, and anything bigger than one attribute, such as a chat message history or a file, has to be split by the application into pieces and put back together on the other side.

Designing a service for your own app

For a custom link between two devices, such as two phones, keep the GATT design small:

  • One custom service UUID that both apps share.
  • One characteristic the client writes to, for data going to the server.
  • One characteristic the server notifies on, for data coming back.
  • A framing format of your own inside those values, so that messages larger than one write can be split and reassembled.

Then decide which side runs the server. Either phone can, and in apps where either user may start a conversation, each phone often runs both a GATT server and a client. That choice is tied to the central and peripheral roles, which decide who connects to whom.

Frequently asked questions

Do I need a registered UUID for my own service?

No. The Bluetooth SIG registers 16-bit UUIDs for standard services, but a custom service uses a 128-bit UUID you generate yourself. Apple's guide suggests the uuidgen command for this.

What is the difference between a notification and an indication?

Both let a server push a characteristic value to a client that has subscribed. An indication must be confirmed by the client, so the server knows it arrived. A notification is not confirmed.

Sources

Build it with Offline Protocol

The Offline Protocol networking page explains how the mesh SDK carries traffic between nearby devices over Bluetooth LE with its own application protocol, which is not Bluetooth SIG Mesh, and what range and capacity depend on.

Read the transport and routing docs