GATT Server#
Generic Attribute Profile (GATT) server implementation: services, characteristics, host- vs firmware-maintained attributes, and notifications/indications from the server.
GATT Server Implementation#
The Generic Attribute Profile (GATT) server is the data model used by Bluetooth Low Energy (BLE) devices to expose services and characteristics. This section describes implementing a GATT server, which is commonly used by peripheral devices.
Note: While peripherals commonly act as GATT servers, GATT roles (Client/Server) are independent of GAP roles (Central/Peripheral). A peripheral can also act as a GATT client, and a central can act as a GATT server.
GATT Server Architecture#
GATT Database Structure:
Service
├── Included Service (optional)
├── Characteristic 1
│ ├── Value
│ ├── Descriptor (e.g., Client Characteristic Configuration)
│ └── Descriptor (e.g., User Description)
├── Characteristic 2
│ └── ...Key Concepts:
Service: Collection of related characteristics (for example, Battery Service, Heart Rate Service)
Characteristic: Data value with properties (read, write, notify, indicate)
Descriptor: Metadata about characteristics (for example, notification enable, format description)
Creating a GATT Server#
1. Add Services
Use
rsi_ble_add_service()to add a service to the GATT databaseSpecify service UUID (16-bit SIG UUID or 128-bit custom UUID)
Service handle is returned for adding characteristics
2. Add Characteristics
Use
rsi_ble_add_attribute()to add characteristics to a serviceSpecify characteristic UUID, properties (read, write, notify, indicate), and permissions
Characteristic handle is returned for value operations
3. Set Characteristic Values
When services are maintained in firmware: Use
rsi_ble_set_local_att_value()to set and update characteristic valuesValues can be updated at runtime as data changes
4. Handle Client Requests
Register GATT callbacks using
rsi_ble_gatt_register_callbacks()When services are maintained in firmware (default): The firmware automatically handles read/write responses
When services are maintained on the host (ATT_MAINTAIN_IN_HOST): Application must manually respond to requests
Handle read requests:
rsi_ble_read_req_t(throughrsi_ble_on_read_req_event_tcallback) - respond withrsi_ble_gatt_read_response()Handle write requests:
rsi_ble_event_write_t(throughrsi_ble_on_gatt_write_event_tcallback) - respond withrsi_ble_gatt_write_response()Handle prepare write:
rsi_ble_event_prepare_write_t(throughrsi_ble_on_gatt_prepare_write_event_tcallback) - respond withrsi_ble_gatt_prepare_write_response()Handle execute write:
rsi_ble_execute_write_t(throughrsi_ble_on_execute_write_event_tcallback) - process queued writes
For request/response APIs (for example, rsi_ble_gatt_read_response(), rsi_ble_gatt_write_response(), rsi_ble_gatt_prepare_write_response()), see the BLE Server. For callback structures and event types (for example, rsi_ble_read_req_t, rsi_ble_on_execute_write_event_t), see Callbacks Declarations (bt-low-energy8).
GATT Server Management#
The following APIs are available for GATT server management. See the BLE Server for supported operations and limitations.
Removing Services:
Use
rsi_ble_remove_gatt_service()to remove a service from the GATT databaseRequires the service handle returned when the service was added
All characteristics and descriptors within the service are removed automatically
Removing Attributes:
Use
rsi_ble_remove_gatt_attibute()to remove a specific attribute (characteristic or descriptor) from a serviceRequires both the service handle and the attribute handle
Reading Local Attribute Values:
Use
rsi_ble_get_local_att_value()to read the current value of a local attributeReturns the attribute value in the response structure
Note: This API can only be used if the service is maintained inside the firmware (not in host)
Characteristic Properties#
Read Property:
Central device can read the characteristic value
When services are maintained in firmware: Read responses are handled automatically by firmware
When services are maintained on the host: Handle
rsi_ble_read_req_t(throughrsi_ble_on_read_req_event_tcallback) and respond withrsi_ble_gatt_read_response()
Write Property:
Central device can write to the characteristic value
When services are maintained in firmware: Write responses are handled automatically by firmware
When services are maintained on the host: Handle
rsi_ble_event_write_tand respond withrsi_ble_gatt_write_response()
Notify Property:
Peripheral can send notifications to central device
Central device enables notifications through Client Characteristic Configuration Descriptor (CCCD)
Use
rsi_ble_notify_value()to send notification
Indicate Property:
Peripheral can send indications to central device (requires acknowledgment)
Central device enables indications through CCCD
Use
rsi_ble_indicate_value()to send indicationWait for confirmation callback (
rsi_ble_on_event_indicate_confirmation_t) before sending next indicationOr use
rsi_ble_indicate_value_sync()which automatically waits for confirmation
GATT Server Best Practices#
Service Organization: Group related characteristics into logical services
UUID Selection: Use 16-bit Bluetooth SIG UUIDs for standard services, 128-bit UUIDs for custom services
Value Updates:
When services are maintained in firmware: Update characteristic values using
rsi_ble_set_local_att_value()when data changes
Error Handling: Respond to invalid requests with
rsi_ble_att_error_response()using appropriate error codesMTU Exchange: MTU exchange is driven by ATT roles (not GAP roles). As an ATT Server (GATT Server), respond to MTU exchange requests from the ATT Client using
rsi_ble_mtu_exchange_resp()whenRSI_BLE_MTU_EXCHANGE_FROM_HOSTis enabled. Note: A device can be both ATT Client and ATT Server simultaneously.
Characteristic Notifications and Indications#
Notifications and indications allow the GATT server to push data to the GATT client without the client explicitly requesting it. This is essential for real-time data applications.
Notifications vs Indications#
Notifications:
Unacknowledged: No confirmation from central device
Lower Latency: Faster transmission, no waiting for acknowledgment
Use Case: High-frequency data updates where occasional loss is acceptable (for example, sensor readings)
API:
rsi_ble_notify_value()
Indications:
Acknowledged: Central device must confirm receipt
Higher Reliability: Guaranteed delivery (within supervision timeout)
Use Case: Important data that must be received (for example, alerts, critical status)
API:
rsi_ble_indicate_value()orrsi_ble_indicate_value_sync()
Enabling Notifications/Indications#
GATT server — notify and indicate characteristics:
Define the characteristic with notify and/or indicate in the GATT database (see Implementation Steps below), apply the correct update path for firmware- vs host-maintained services, then push updates after the central enables the CCCD (Client Characteristic Configuration Descriptor (CCCD) as mentioned below).
Client Characteristic Configuration Descriptor (CCCD):
Central device enables notifications/indications by writing to the CCCD
CCCD value:
0x0001= notifications enabled,0x0002= indications enabledPeripheral receives
rsi_ble_event_write_tevent when CCCD is writtenCheck the characteristic handle and value to determine if notifications/indications are enabled
Implementation Steps:
Set the notify and/or indicate property bits in the
propertyfield ofrsi_ble_req_add_att_swhen callingrsi_ble_add_attribute().Firmware-maintained services (default): update the characteristic with
rsi_ble_set_local_att_value()as in GATT Server Implementation.Host-maintained services (
RSI_BLE_ATT_MAINTAIN_IN_HOSTinRSI_BLE_ATT_CONFIG_BITMAP): the characteristic value is in application memory and can be updated from application code.Add the CCCD descriptor when creating the characteristic (explicitly as part of the attribute definition).
Monitor CCCD writes through
rsi_ble_event_write_tevents.Track which characteristics have notifications/indications enabled.
After the CCCD is enabled, use
rsi_ble_notify_value()orrsi_ble_indicate_value()to push updates when data changes.
Note: For characteristic values larger than 20 bytes, Silicon Labs recommends host-maintained storage (
RSI_BLE_ATT_MAINTAIN_IN_HOST, step 3). For firmware-maintained services, the WiSeConnect BLE API description forrsi_ble_set_local_att_value()documents attribute data size less than 20 bytes during service creation as a rule.
Sending Notifications#
Basic Notification:
// Send notification for a characteristic
rsi_ble_notify_value(remote_dev_addr, char_handle, data, data_len);Notification Best Practices:
Check if notifications are enabled before sending
Use appropriate connection interval for data rate
Buffer management: Use
rsi_ble_set_wo_resp_notify_buf_info()to configure buffer behavior
Sending Indications#
Basic Indication:
// Send indication (asynchronous)
rsi_ble_indicate_value(remote_dev_addr, char_handle, data, data_len);
// Or synchronous (wait for confirmation)
rsi_ble_indicate_value_sync(remote_dev_addr, char_handle, data, data_len);Indication Flow:
Send indication using
rsi_ble_indicate_value()Wait for confirmation callback (
rsi_ble_on_event_indicate_confirmation_t) before sending next indicationOnly send next indication after confirmation received
Use
rsi_ble_indicate_value_sync()for simplified synchronous operation (handles waiting automatically)
Indication Best Practices:
Always wait for confirmation before sending next indication
Implement timeout handling for missing confirmations
Use indications for critical data that must be delivered
Consider connection supervision timeout when waiting for confirmations
APIs Used in This Section#
Topic | APIs / symbols | Reference |
|---|---|---|
GATT server — database |
| |
GATT server — responses / ATT |
| |
Host-maintained ATT — events / callbacks |
| |
Build / feature flags (prose) |
| |
Notifications / indications |
| |
Indications (synchronous) |
| |
Callbacks |
|