Characteristic es una unidad fundamental de datos en Bluetooth Low Energy a través de la cual un Central lee o escribe información en un dispositivo periférico. Cada Characteristic pertenece a un servicio GATT específico, tiene un UUID único y un conjunto de propiedades (read, write, notify, indicate) que definen las operaciones posibles. Según la Bluetooth Core Specification 5.4 (2023), Bluetooth SIG ha especificado más de 500 características estándar para dispositivos médicos, de fitness e industriales. Los desarrolladores crean características personalizadas para transmitir cualquier tipo de datos de usuario, desde lecturas de sensores hasta comandos de control del dispositivo.
Puntos clave
Una Characteristic es un atributo del protocolo GATT que contiene un valor y metadatos. En la arquitectura BLE, los datos no se transfieren directamente entre dispositivos, sino mediante la lectura y escritura de los valores de las características del servicio. Si un servicio es una carpeta, entonces una Characteristic es un archivo dentro de esa carpeta.
Cada Characteristic consta de tres componentes: declaración (declaration), valor (value) y descriptores (descriptors). La declaración contiene el UUID de la característica y sus propiedades. El valor son los datos reales transferidos entre Central y Peripheral. Los descriptores proporcionan configuración adicional.
Según la Bluetooth Core Specification 5.4 (2023), todos los intercambios de datos en BLE se producen mediante operaciones sobre características. Incluso los perfiles estándar, como Heart Rate Profile o Battery Service, se basan en un conjunto de características con UUID predefinidos. Esto garantiza la compatibilidad de dispositivos de diferentes fabricantes sin configuración previa.
Es importante que el desarrollador comprenda: cada Characteristic puede admitir diferentes combinaciones de propiedades. Una característica puede ser solo de lectura, otra de escritura y una tercera de notificaciones. La elección correcta de las propiedades determina el caso de uso y el consumo energético del dispositivo.
Las propiedades (properties) de una característica definen qué operaciones están permitidas sobre ella. Es una máscara de bytes donde cada bit activa o desactiva una operación específica. A continuación se enumeran las propiedades principales.
| Propiedad | Bit | Descripción | Uso típico |
|---|---|---|---|
| Read | 0x02 | Central puede leer el valor actual | Estado, nivel de batería, configuración |
| Write | 0x08 | Central puede escribir un nuevo valor | Comandos de control, ajustes |
| Notify | 0x10 | Peripheral envía el valor sin confirmación | Datos en flujo (pulso, temperatura) |
| Indicate | 0x20 | Peripheral envía el valor con confirmación | Datos críticos (alertas, estados) |
| Write Without Response | 0x04 | Escritura sin esperar confirmación del servidor | Transmisión de comandos de alta velocidad |
Los permisos (permissions) son el nivel de acceso a nivel del servidor GATT. A diferencia de las propiedades, que se declaran en la declaración de la característica, los permisos se verifican en cada operación. Pueden incluir requisitos de cifrado y autenticación.
Bluetooth SIG ha especificado más de 500 características estándar que cubren la mayoría de los casos de uso comunes de BLE. El uso de UUID estándar garantiza que cualquier dispositivo receptor interprete correctamente los datos sin configuración previa.
Estas son las características estándar más utilizadas:
| UUID | Nombre | Tipo de dato | Servicio |
|---|---|---|---|
| 0x2A19 | Battery Level | uint8 (0–100%) | Battery Service |
| 0x2A37 | Heart Rate Measurement | uint8 + flags | Heart Rate |
| 0x2A6E | Temperature | int16 (0.01°C) | Environmental Sensing |
| 0x2A6F | Humidity | uint16 (0.01%) | Environmental Sensing |
| 0x2A00 | Device Name | Cadena UTF-8 | Generic Access |
| 0x2A01 | Appearance | uint16 | Generic Access |
Si una característica estándar existente cubre su tarea, úsela. Esto simplifica la certificación Bluetooth y mejora la compatibilidad con el ecosistema. Cree características personalizadas solo para datos únicos que no estén en el registro SIG.
La creación de una característica se realiza en el lado de Peripheral, el dispositivo que proporciona los datos. Veamos las implementaciones en iOS (Swift) y Android (Java).
Core Bluetooth proporciona la clase CBMutableCharacteristic para crear una característica con un UUID, propiedades y un valor inicial.
import CoreBluetooth
let characteristicUUID = CBUUID("2A19") // Característica de nivel de batería
let characteristic = CBMutableCharacteristic(
type: characteristicUUID,
properties: [.read, .notify],
value: nil,
permissions: [.readable]
)
// Actualizar valor al cambiar
let batteryData = Data([batteryLevel]) // uint8
peripheralManager.updateValue(
batteryData,
for: characteristic,
onSubscribedCentrals: nil
)
En Android, una característica se crea mediante BluetoothGattCharacteristic con un UUID, propiedades y permisos.
import android.bluetooth.*;
UUID charUuid = UUID.fromString("00002A19-0000-1000-8000-00805F9B34FB");
BluetoothGattCharacteristic characteristic =
new BluetoothGattCharacteristic(
charUuid,
BluetoothGattCharacteristic.PROPERTY_READ
| BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ
);
// Establecer el valor
characteristic.setValue(batteryLevel, BluetoothGattCharacteristic.FORMAT_UINT8, 0);
gattServer.notifyCharacteristicChanged(device, characteristic, false);
Las operaciones sobre una Characteristic se dividen en tres tipos: lectura (read), escritura (write) y notificaciones (notify/indicate). La elección depende del escenario: los datos bajo demanda se leen, los comandos se escriben y los datos en flujo se suscriben a notificaciones.
Read: Central envía una solicitud para leer el valor de la característica. Peripheral responde con el valor actual. La operación es síncrona y requiere una solicitud explícita de cada parte. Se utiliza para datos que cambian con poca frecuencia: versión de firmware, número de serie, configuración.
Write: Central envía datos a Peripheral. Hay dos modos: Write with Response (confirmación de Peripheral) y Write Without Response (sin confirmación). Write with Response garantiza la entrega: Peripheral envía una confirmación después de la escritura. Write Without Response es más rápido pero no garantiza la entrega.
Notify e Indicate: Peripheral inicia la transmisión de datos a Central. Con Notify, los datos se envían sin confirmación; si Central no recibe el paquete, se pierde. Con Indicate, Central envía una confirmación (nivel PDU), lo que garantiza la entrega. Indicate es más lento pero más confiable. Para suscribirse a notificaciones, Central escribe el valor 0x0001 en el CCCD (Client Characteristic Configuration Descriptor).
MTU (Maximum Transmission Unit) define el tamaño máximo de un solo paquete de datos BLE. Por defecto, el MTU es de 23 bytes, de los cuales 3 bytes son el encabezado; la carga útil (ATT payload) es de 20 bytes. Esto es suficiente para la mayoría de los datos de sensores, pero no para transferencias de archivos o configuraciones grandes.
Bluetooth Core Specification 5.4 admite negociación de MTU: Central y Peripheral pueden acordar un tamaño de paquete mayor de hasta 517 bytes. El proceso funciona así: Central envía una solicitud MTU Exchange con su MTU propuesto; Peripheral responde con su MTU; se utiliza el menor de los dos valores.
// iOS solicita MTU al conectar
// El MTU máximo en iOS es 185 bytes
func peripheral(
_ peripheral: CBPeripheral,
didDiscoverServices error: Error?
) {
// Solicitar MTU para un periférico específico
peripheral.maximumWriteValueLength(for: .withResponse)
}
Según Bluetooth SIG (2023), aumentar el MTU de 23 a 185 bytes reduce la sobrecarga de transmisión de datos hasta en un 80% gracias a la reducción del número de paquetes. Para aplicaciones que transmiten lecturas de alta frecuencia (por ejemplo, ECG o acelerómetro), el aumento del MTU es crítico para la estabilidad del flujo.
Preguntas frecuentes
La especificación BLE no limita la cantidad de características en un servicio. En la práctica, la limitación está determinada por la memoria disponible del servidor GATT y los requisitos de rendimiento. Para dispositivos integrados, se recomienda no más de 10–15 características por servicio.
Notify envía datos sin confirmación: el paquete puede perderse sin notificar al remitente. Indicate requiere confirmación (ACK) a nivel de protocolo, lo que garantiza la entrega. Indicate es más lento pero más confiable. Para datos críticos (alertas, comandos), use Indicate.
Sí, una característica puede tener una combinación de propiedades. Por ejemplo, una característica de configuración puede admitir Read (lectura del valor actual) y Write (cambio de la configuración). Combine las propiedades según su caso de uso.
Utilice la negociación de MTU para aumentar el tamaño del paquete a 185–517 bytes. Si los datos siguen siendo más grandes, implemente la fragmentación a nivel de aplicación: divida los datos en varias solicitudes secuenciales con control de integridad.
Si su tarea está cubierta por una característica estándar, use UUID del registro de Bluetooth SIG. Esto simplifica la certificación y garantiza la compatibilidad con el ecosistema. Cree UUID personalizados solo para datos únicos de terceros.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también