La couche Generic Attribute Profile (GATT) définit comment les dispositifs Bluetooth Low Energy exposent les données aux clients. Pour les ingénieurs intégrant des modules Bluetooth dans des produits, l’architecture de services GATT détermine directement les performances, la consommation énergétique et l’interopérabilité. Cet article couvre les décisions pratiques de conception GATT pour les produits basés sur modules.
Hiérarchie GATT
GATT organise les données en une hiérarchie de quatre niveaux :
| Niveau | Description | Exemple |
|---|---|---|
| Profile | Collection de services pour un cas d’usage | Heart Rate Profile |
| Service | Groupe de characteristics reliées | Heart Rate Service (0x180D) |
| Characteristic | Valeur nommée avec propriétés | Heart Rate Measurement (0x2A37) |
| Descriptor | Métadonnées d’une characteristic | Client Characteristic Configuration (0x2902) |
Un module implémente typiquement un ou plusieurs services primaires. Les services secondaires ne sont significatifs que lorsqu’un autre service les référence — en pratique, la plupart des designs de modules les évitent.
Conception de Services
Enregistrement de Service Primaire
Chaque service est identifié par un UUID 128 bits. Deux stratégies d’allocation :
- UUIDs 16 bits (0x1800–0x26FF) : Assignés par Bluetooth SIG pour les services standardisés. Utiliser quand le module implémente un profil standard (ex. : Battery Service 0x180F).
- UUIDs custom 128 bits : Pour les services propriétaires. Générer un UUID de base et incrémenter les bytes inférieurs pour chaque service et characteristic.
Pattern courant d’UUID de base :
Base: 6E40XXXX-B5A3-F393-E0A9-E50E24DCCA9E Service: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E Char 1: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E Char 2: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E
Cette approche, utilisée par le service UART de Nordic, simplifie la gestion des UUIDs sur une gamme de produits.
Propriétés de Characteristic
Chaque characteristic déclare des propriétés contrôlant l’interaction client :
| Propriété | Opcode | Direction | Cas d’usage |
|---|---|---|---|
| Read | 0x0A | Client → Serveur | Valeurs de configuration |
| Write | 0x12 | Client → Serveur | Commandes de contrôle |
| Write Without Response | 0x52 | Client → Serveur | Commandes haute fréquence |
| Notify | — | Serveur → Client | Streaming de données capteurs |
| Indicate | — | Serveur → Client | Alertes critiques |
| Broadcast | — | Serveur → Tous | Advertising type beacon |
Notification vs Indication
Les deux poussent les données du serveur vers le client, mais avec des garanties de fiabilité différentes :
- Notify (ATT_HANDLE_VALUE_NOTIFICATION) : Pas d’accusé. Latence : ~3 ms/paquet à PHY 1 Mbps. Débit : jusqu’à 270 kbps avec MTU 23 bytes, ~800 kbps avec MTU 247 bytes.
- Indicate (ATT_HANDLE_VALUE_INDICATION) : Requiert confirmation ATT du client. Ajoute un round-trip (~6–10 ms). Pour les données où la confirmation de livraison est obligatoire.
Pour un module streamant des données capteur à 10 Hz, Notify est le choix évident — l’échantillon suivant supplante tout paquet perdu. Pour un module rapportant des événements d’alarme, Indicate garantit que le client a reçu l’alerte.
Conception de Descriptors
Chaque characteristic supportant Notify ou Indicate doit inclure un Client Characteristic Configuration Descriptor (CCCD, UUID 0x2902). Écrire 0x0001 active Notify ; 0x0002 active Indicate ; 0x0000 désactive les deux.
Descriptors optionnels recommandés :
| Descriptor | UUID | Objectif |
|---|---|---|
| Characteristic User Description | 0x2901 | Nom lisible |
| Characteristic Presentation Format | 0x2904 | Unité, exposant, type de donnée |
| Characteristic Extended Properties | 0x2900 | Support Reliable Write |
Le descriptor Presentation Format est particulièrement utile pour les modules servant plusieurs types de capteurs — il permet à l’application cliente de détecter automatiquement si une valeur représente la température (0x07, unités 0x272F = Celsius) ou l’humidité (0x06, unités 0x272F = pourcentage).
Optimisation MTU et Débit
Le MTU ATT par défaut est 23 bytes (20 bytes payload). Les smartphones modernes supportent MTU 247 ou plus. Le module doit demander l’échange MTU lors de la connexion :
// Pseudocode pour négociation MTU ble_att_exchange_mtu_request(247); // Après échange, MTU effectif = min(local, distant) // Payload par notification = MTU - 3 bytes en-tête ATT
Comparaison de débit à différentes valeurs MTU (intervalle 30 ms, PHY 1 Mbps) :
| MTU | Payload/Paquet | Paquets/Intervalle | Débit |
|---|---|---|---|
| 23 | 20 B | 4 | 21 kbps |
| 185 | 182 B | 1 | 48 kbps |
| 247 | 244 B | 1 | 65 kbps |
Pour les modules avec Data Length Extension (DLE) (Bluetooth 4.2+), activer DLE avec un grand MTU peut pousser le débit au-delà de 800 kbps sur PHY 1 Mbps.
Exemple Pratique : Service Multi-Capteurs
Design flat pour un module intégrant température, humidité et accéléromètre :
Service: 6E400001-... (Custom Sensor Service) ├── Char: 6E400002-... (Temperature, Read|Notify) │ └── CCCD: 0x2902 │ └── Presentation Format: 0x2904 (int16, 0.01°C, unit Celsius) ├── Char: 6E400003-... (Humidity, Read|Notify) │ └── CCCD: 0x2902 │ └── Presentation Format: 0x2904 (uint16, 0.01%, unit percentage) ├── Char: 6E400004-... (Acceleration XYZ, Notify) │ └── CCCD: 0x2902 └── Char: 6E400005-... (Sampling Rate, Read|Write)
La characteristic Sampling Rate permet au client de configurer la fréquence de notification — écrire 10 pour 10 Hz, écrire 0 pour désactiver toutes les notifications.
Impact Énergétique
Chaque notification consomme ~1.2 ms de temps radio actif à 1 Mbps. À 10 Hz avec payloads de 20 bytes :
- Temps radio actif : ~12 ms / 1000 ms = 1.2% duty cycle
- Courant estimé : 0.012 × 8 mA (TX) + 0.988 × 5 µA (sleep) ≈ 100 µA moyen
- Durée de vie batterie CR2032 (220 mAh) : ~2200 heures ≈ 91 jours
En réduisant à 1 Hz : le courant moyen descend à ~13 µA, prolongant la durée de vie batterie à ~1.9 ans.
Erreurs de Conception Courantes
- Services trop fragmentés : Répartir les données reliées sur plusieurs services oblige le client à de multiples découvertes de services. Regrouper les characteristics reliées dans un seul service.
- CCCD absent : Une characteristic avec Notify mais sans CCCD provoquera le rejet du service par certains stacks. Toujours inclure CCCD pour les characteristics notifiables.
- Collisions UUID : Utiliser des UUIDs 128 bits aléatoires sans pattern de base systématique risque des collisions entre variantes de produits. Adopter un UUID de base avec bytes inférieurs séquentiels.
- Indications excessives : Utiliser Indicate pour des données haute fréquence (ex. : IMU 50 Hz) gaspille la bande passante en confirmations. Réserver Indicate pour les événements basse fréquence et haute fiabilité.
- Ignorer Presentation Format : Sans descriptor 0x2904, les applications clientes doivent hard-coder l’interprétation des données, brisant l’interopérabilité avec les browsers GATT génériques comme nRF Connect.
Conclusion
L’architecture de services GATT est le contrat de couche applicative entre un module Bluetooth et son hôte. Une organisation de services réfléchie, une sélection appropriée de propriétés de characteristic, et un usage correct de descriptors déterminent si un module s’intègre proprement dans les écosystèmes tiers ou devient un fardeau de debugging. Les principes ci-dessus — design de service flat, Notify pour le streaming, allocation UUID systématique, et optimisation MTU — constituent une base solide pour le développement de produits basés sur modules.