Die Generic Attribute Profile (GATT)-Schicht definiert, wie Bluetooth Low Energy-Geräte Daten für Clients bereitstellen. Für Ingenieure, die Bluetooth-Module in Produkte integrieren, bestimmt die GATT-Service-Architektur direkt die Anwendungsperformance, den Energieverbrauch und die Interoperabilität. Dieser Artikel behandelt praktische GATT-Designentscheidungen für modulbasierte Produkte.

GATT-Hierarchie

GATT organisiert Daten in einer vierstufigen Hierarchie:

Ebene Beschreibung Beispiel
Profile Service-Sammlung für einen Use-Case Heart Rate Profile
Service Gruppe verwandter Characteristics Heart Rate Service (0x180D)
Characteristic Benannter Wert mit Properties Heart Rate Measurement (0x2A37)
Descriptor Metadaten einer Characteristic Client Characteristic Configuration (0x2902)

Ein Modul implementiert typischerweise einen oder mehrere Primary Services. Secondary Services sind nur sinnvoll, wenn ein anderer Service sie referenziert — praktisch vermeiden die meisten Moduldesigns sie.

Service-Design

Primary Service-Registrierung

Jeder Service wird durch eine 128-bit UUID identifiziert. Zwei Zuweisungsstrategien:

  • 16-bit UUIDs (0x1800–0x26FF): Von Bluetooth SIG für standardisierte Services zugewiesen. Verwenden, wenn das Modul ein Standardprofil implementiert (z.B.: Battery Service 0x180F).
  • 128-bit Custom UUIDs: Für proprietäre Services. Basis-UUID generieren und die unteren Bytes für jeden Service und Characteristic inkrementieren.

Häufiges Basis-UUID-Pattern:

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

Dieser Ansatz, vom Nordic UART-Service verwendet, vereinfacht das UUID-Management über eine Produktlinie.

Characteristic-Properties

Jede Characteristic deklariert Properties, die die Client-Interaktion steuern:

Property Opcode Richtung Use-Case
Read 0x0A Client → Server Konfigurationswerte
Write 0x12 Client → Server Steuerkommandos
Write Without Response 0x52 Client → Server Hochfrequenz-Kommandos
Notify Server → Client Sensor-Daten-Streaming
Indicate Server → Client Kritische Alarme
Broadcast Server → All Beacon-Advertising

Notification vs Indication

Beide senden Daten vom Server zum Client, aber mit unterschiedlichen Zuverlässigkeitsgarantien:

  • Notify (ATT_HANDLE_VALUE_NOTIFICATION): Keine Bestätigung. Latenz: ~3 ms/Paket bei 1 Mbps PHY. Throughput: bis 270 kbps mit 23-byte MTU, ~800 kbps mit 247-byte MTU.
  • Indicate (ATT_HANDLE_VALUE_INDICATION): Erfordert ATT-Bestätigung vom Client. Ein zusätzlicher Round-Trip (~6–10 ms). Für Daten mit obligatorischer Lieferbestätigung.

Bei einem Modul, das Sensordaten mit 10 Hz streamt, ist Notify die klare Wahl — die nächste Probe ersetzt jedes verlorene Paket. Für Alarmereignisse gewährleistet Indicate, dass der Client die Warnung erhielt.

Descriptor-Design

Jede Characteristic mit Notify oder Indicate-Support muss einen Client Characteristic Configuration Descriptor (CCCD, UUID 0x2902) enthalten. Schreiben von 0x0001 aktiviert Notify; 0x0002 aktiviert Indicate; 0x0000 deaktiviert beide.

Empfohlene optionale Descriptors:

Descriptor UUID Zweck
Characteristic User Description 0x2901 Lesbarer Name
Characteristic Presentation Format 0x2904 Einheit, Exponent, Datentyp
Characteristic Extended Properties 0x2900 Reliable Write-Support

Der Presentation Format Descriptor ist besonders wertvoll für Module mit mehreren Sensortypen — er ermöglicht der Client-Anwendung zu erkennen, ob ein Wert Temperatur (0x07, Einheiten 0x272F = Celsius) oder Feuchtigkeit (0x06, Einheiten 0x272F = Prozent) repräsentiert.

MTU und Throughput-Optimierung

Der Standard-ATT-MTU ist 23 Bytes (20 Bytes Payload). Moderne Smartphones unterstützen MTU 247 oder höher. Das Modul sollte MTU-Exchange während der Verbindung anfordern:

// Pseudocode für MTU-Negotiation
ble_att_exchange_mtu_request(247);
// Nach Exchange: effektiver MTU = min(lokal, remote)
// Payload pro Notification = MTU - 3 Bytes ATT-Header

Throughput-Vergleich bei verschiedenen MTU-Werten (Verbindungsintervall 30 ms, 1 Mbps PHY):

MTU Payload/Paket Pakete/Intervall Throughput
23 20 B 4 21 kbps
185 182 B 1 48 kbps
247 244 B 1 65 kbps

Für Module mit Data Length Extension (DLE) (Bluetooth 4.2+) kann DLE plus großer MTU den Throughput auf über 800 kbps bei 1 Mbps PHY steigern.

Praxisbeispiel: Multi-Sensor-Service

Flat-Design für ein Modul mit Temperatur-, Feuchtigkeits- und Accelerometer-Sensoren:

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)

Die Sampling Rate Characteristic ermöglicht dem Client die Konfiguration der Notifikationsfrequenz — 10 setzen 10 Hz, 0 deaktiviert alle Notifications.

Energieeffizienz

Jede Notification verbraucht ~1.2 ms Radio-Aktivzeit bei 1 Mbps. Bei 10 Hz mit 20-Byte Payloads:

  • Radio-Aktivanteil: ~12 ms / 1000 ms = 1.2% Duty Cycle
  • Estimativer Strom: 0.012 × 8 mA (TX) + 0.988 × 5 µA (Sleep) ≈ 100 µA average
  • CR2032 Batterielebensdauer (220 mAh): ~2200 Stunden ≈ 91 Tage

Reduktion auf 1 Hz: average Strom sinkt auf ~13 µA, Batterielebensdauer verlängert auf ~1.9 Jahre.

Häufige Design-Fehler

  • Übersegmentierte Services: Verwandte Daten über mehrere Services verteilen erfordert mehrere Service-Discovery-Operationen. Verwandte Characteristics in einem Service zusammenfassen.
  • Fehlender CCCD: Eine Characteristic mit Notify ohne CCCD führt dazu, dass einige Stacks den Service ablehnen. CCCD für notifiable Characteristics immer einfügen.
  • UUID-Kollisionen: Random 128-bit UUIDs ohne systematisches Basis-Pattern riskieren Kollisionen zwischen Produktvarianten. Basis-UUID mit sequenziellen unteren Bytes verwenden.
  • Übermäßige Indications: Indicate für hochfrequente Daten (z.B.: 50 Hz IMU) verschwendet Bandbreite für Bestätigungen. Indicate auf niederfrequente, hochzuverlässige Events beschränken.
  • Presentation Format ignoriert: Ohne 0x2904 Descriptor müssen Client-Anwendungen Dateninterpretation hard-codieren, was Interoperabilität mit generischen GATT-Browsers wie nRF Connect zerstört.

Fazit

GATT-Service-Architektur ist der Application-Layer-Vertrag zwischen einem Bluetooth-Modul und seinem Host. Durchdachte Service-Organisation, passende Characteristic-Property-Auswahl und korrekter Descriptor-Einsatz bestimmen, ob ein Modul sauber in Drittanbieter-Ecosystems integriert wird oder ein Debugging-Burden wird. Die obigen Prinzipien — Flat-Service-Design, Notify für Streaming, systematische UUID-Zuweisung und MTU-Optimierung — bilden eine verlässliche Grundlage für modulbasierte Produktentwicklung.