BLE GATT entwerfen: UUIDs, Datenformate, Notifications und Versionskompatibilität

Eine BLE-Verbindung kann funktionieren, obwohl die Produktintegration scheitert. Die App findet möglicherweise die falsche Characteristic, dekodiert einen vorzeichenbehafteten Messwert falsch oder empfängt nach einem Firmware-Update keine Aktualisierungen mehr. Eine nutzbare GATT-Schnittstelle braucht eine schriftliche Vereinbarung über Identität, Bytes, Zustellungssemantik, Sicherheit und Versionsänderungen. Dieser Leitfaden entwickelt eine solche Vereinbarung für eine eigene Sensor- und Steuerschnittstelle.

Die Schnittstelle vor der App definieren

Dokumentieren Sie für jeden Service und jede Characteristic UUID, Eigenschaften, Berechtigungen, maximale Länge und Fehlerantworten. Verwenden Sie einen Bluetooth-SIG-Service nur dann, wenn dessen definierte Bedeutung und Format zum Produkt passen. Vergeben Sie für proprietäre Semantik eine stabile 128-Bit-UUID, statt eine nicht zugewiesene Kurz-UUID zu erfinden. Die Datentypenspezifikation der SIG beschränkt kurze Service-UUIDs auf von der SIG zugewiesene Werte.

Pflegen Sie die UUIDs in einem versionskontrollierten Register, das Firmware, App und Testwerkzeuge gemeinsam nutzen. Verwenden Sie den Gerätenamen nicht als einziges Identitätsmerkmal: Namen können sich ändern, und mehrere Geräte können denselben Namen aussenden. Ebenso sollten Attribut-Handles nicht über Firmware-Versionen hinweg fest einprogrammiert werden. Ermitteln Sie den Service, wählen Sie die gewünschte Instanz und lösen Sie die Characteristics innerhalb dieses Services auf.

Characteristic Empfohlene Operation Zu dokumentierende Vereinbarung
Protokollinformationen Lesen Haupt- und Nebenversion des Formats, Fähigkeiten und maximaler Anwendungsrahmen
Messdatenstrom Notification Einheiten, Sequenzzähler, Zeitbezug und Überlaufstrategie
Konfiguration Lesen und Schreiben mit Antwort Bereiche, Autorisierung, Validierung und Zeitpunkt der dauerhaften Speicherung
Befehlsresultat Indication oder Notification mit Anwendungsbestätigung Transaktions-ID, Ergebniscode und Bedeutung des Abschlusses

Ein testbares Byteformat festlegen

Das folgende Beispiel ist ein 12-Byte-Messrahmen und kein standardisiertes Bluetooth-Profil. Alle Mehrbytefelder verwenden Little Endian. Die Festkommadarstellung der Temperatur vermeidet Abhängigkeiten von der Gleitkommaserialisierung einer Programmiersprache. Ein separater Lesezugriff auf die Protokollinformationen liefert die Nebenversion und die unterstützten Fähigkeiten.

Offset Feld Definition
0 major Vorzeichenlose 8-Bit-Hauptversion, anfangs 1
1 flags Bit 0 bedeutet gültige Temperatur; übrige Bits reserviert und null
2–3 sequence Vorzeichenloser 16-Bit-Zähler, modulo 65536
4–7 uptime_ms Vorzeichenlose 32-Bit-Abtastzeit seit dem Start; Überlauf modulo 2³²
8–9 temperature Vorzeichenbehaftet, 16 Bit, 0,01 °C pro Schritt; bei Ungültigkeit ignorieren
10–11 battery_mV Vorzeichenlose 16-Bit-Millivolt; 65535 bedeutet nicht verfügbar

In diesem Beispiel werden Sequenznummer und Laufzeit beim Neustart zurückgesetzt. Eine beim Sitzungsaufbau gelesene Startkennung unterscheidet Neustarts vom Zählerüberlauf. Negative Temperaturen, ungültige Flags, abgeschnittene Rahmen und Zählerüberläufe gehören in gemeinsam verwendete Referenz-Testvektoren. Dieser Python-Decoder zeigt die explizite Validierung:

import struct

def decode_v1(payload):
    if len(payload) != 12:
        raise ValueError("expected 12 bytes")
    major, flags, seq, ms, temp, mv = struct.unpack("<BBHIhH", payload)
    if major != 1 or flags & 0xFE:
        raise ValueError("unsupported schema or flags")
    return {
        "sequence": seq, "uptime_ms": ms,
        "temperature_C": temp / 100 if flags & 1 else None,
        "battery_mV": None if mv == 65535 else mv,
    }

Ein Referenzvektor lautet 01 01 2A 00 E8 03 00 00 2E FB E4 0C: Hauptversion 1, gültige Temperatur, Sequenznummer 42, Laufzeit 1000 ms, −12,34 °C und 3300 mV. Dekodieren Sie ihn auf beiden Seiten, bevor Sie reale Hardware verbinden.

Die strenge Prüfung reservierter Bits bedeutet, dass dieser Decoder neue Flag-Bedeutungen nicht stillschweigend akzeptieren kann. Behalten Sie den v1-Rahmen bei, handeln Sie eine unterstützte Erweiterung aus oder führen Sie ein neues Hauptformat ein. Das Anhängen von Bytes ist nur abwärtskompatibel, wenn der vorhandene Parser ausdrücklich dafür ausgelegt wurde.

Drei BLE-Schnittstellenverträge und ein beispielhafter 12-Byte-Messrahmen mit Trennung zwischen ATT-Bestätigung und Anwendungsabschluss.
Abbildung 1. Ein GATT-Integrationsvertrag umfasst Discovery, Datenstromaufbau und Anwendungsbedeutung. Das 12-Byte-Layout ist ein eigenes Beispiel und kein Bluetooth-Standardprofil.

Abonnement und zuverlässige Anwendungszustellung trennen

Notifications besitzen keine ATT-Bestätigung, Indications dagegen schon. Beides beweist weder die Speicherung eines Messwerts in einer Cloud-Datenbank noch die erfolgreiche Ausführung eines Motorbefehls. Die verbundene BLE-Strecke besitzt eigene Wiederholungsmechanismen; Verbindungsabbrüche, volle Softwarewarteschlangen und App-Neustarts benötigen trotzdem eine Ende-zu-Ende-Regelung. Verwenden Sie Sequenznummern zur Erkennung fehlender Messwerte und Transaktions-IDs zur Zuordnung von Befehlsresultaten. Die zugrunde liegenden Abläufe definiert die ATT-Spezifikation.

Abonnieren Sie über die Plattform-API und prüfen Sie den Abschluss, bevor Sie den Datenstrom als bereit melden. Auf GATT-Ebene aktiviert der Client Characteristic Configuration Descriptor mit UUID 0x2902 Notifications durch 0x0001 beziehungsweise Indications durch 0x0002. Der Abonnementstatus gilt pro Client. Die Persistenz unterscheidet sich bei gebundenen und nicht gebundenen Geräten. Deshalb muss die Wiederverbindung den lokalen Callback wiederherstellen und sicherstellen, dass das Abonnement aktiv ist. Siehe GATT-Spezifikation.

Definieren Sie eine begrenzte Warteschlange und ein dokumentiertes Überlastverhalten: älteste Messwerte verwerfen, nur den neuesten Wert behalten oder die Erfassung pausieren, sofern das Produkt dies erlaubt. Stellen Sie einen Zähler verworfener Messwerte bereit. Unterscheiden Sie bei Befehlen zwischen „angenommen“, „in Ausführung“ und „abgeschlossen“. Die Wiederholung derselben Transaktion nach einem Verbindungsabbruch darf einen Aktor nicht versehentlich zweimal auslösen.

MTU und Plattformunterschiede sichtbar machen

Bei einer herkömmlichen Notification mit einem Handle muss der Wert in ATT_MTU minus 3 Byte passen; zusätzlich beträgt die Obergrenze für einen Attributwert 512 Byte. Die standardmäßige LE-ATT-MTU von 23 lässt somit 20 Byte für diese Notification übrig. Größere Werte erfordern eine vereinbarte Fragmentierung auf Anwendungsebene oder ein anderes geeignetes Übertragungsverfahren. Eine größere MTU wählt weder automatisch einen schnelleren PHY noch erhöht sie die Link-Layer-Datenlänge. Siehe ATT-Paketformate.

Ab Android 14 veranlasst die erste MTU-Anforderung eines GATT-Clients den Stack, 517 anzufordern; spätere Anforderungen werden ignoriert. Bemessen Sie Rahmen anhand des ausgehandelten Callback-Ergebnisses, niemals anhand des angeforderten Werts. Fragen Sie auf Apple-Plattformen maximumWriteValueLength(for:) für die gewählte Schreibart ab, statt Android-Annahmen zu übernehmen. Beachten Sie die Android-Referenz zu BluetoothGatt und die Apple-Referenz zur Schreiblänge.

Führen Sie asynchrone Einrichtungsschritte nacheinander aus, sofern der gewählte Stack die gewünschte Parallelität nicht ausdrücklich unterstützt. Ein erfolgreicher Aufruf bedeutet häufig nur, dass die Anforderung eingereiht wurde; das Ergebnis liefert der Callback. Protokollieren Sie ausgehandelte MTU, ausgewählte Characteristic-UUID, Sicherheitszustand, Abonnementergebnis und Parser-Version gemeinsam.

Kompatibilität zwischen Firmware- und App-Versionen planen

Protokollformatversion, Firmware-Version und Aufbau der GATT-Datenbank sind getrennte Aspekte. Halten Sie innerhalb eines unterstützten Formats die Bedeutung vorhandener Felder stabil. Stellen Sie Fähigkeiten explizit bereit, statt Clients Funktionen aus einer Firmware-Zeichenfolge ableiten zu lassen. Lehnen Sie eine nicht unterstützte Hauptversion mit einer hilfreichen Diagnose ab, bevor Steuerbefehle gesendet werden.

Ändert ein Update die Service-Datenbank, implementieren Sie das zutreffende Service-Changed- und Cache-Verhalten. Database Hash ermöglicht dort, wo verfügbar, die Änderungserkennung. Diese Mechanismen übersetzen keine geänderten Anwendungsdatenformate. Testen Sie Updates und Rollbacks sowohl mit zuvor gebundenen Clients als auch mit Neuinstallationen. Die GATT-Cache-Regeln erläutern die Anforderungen auf Datenbankebene.

Fehler mit einer Freigabematrix aufdecken

Test Zu provozierender Fehler Aufzubewahrender Nachweis
Alte App mit neuer Firmware; neue App mit alter Firmware Unbekannte Hauptversion, fehlendes optionales Feld oder geänderter Aufbau Fähigkeitsabfrage und ausdrückliche Annahme oder Ablehnung
MTU 23 und größere ausgehandelte MTU Zu große Nutzlast, falsche Fragmentlänge oder Abschneiden Empfangene Länge und dekodierter Referenzvektor
Abbruch während Befehl und Abonnement Doppelte Betätigung oder ausbleibender Datenstrom Transaktions-ID, Abonnementabschluss und erster gültiger Messwert
Update und Rollback mit erhaltenen Bindungen Veralteter Handle-Cache oder Zugriff auf falsche Characteristic Discovery-/Cache-Übergang und UUID-Zuordnung
Langsamer Verbraucher und volle Warteschlange Speicherwachstum oder unerklärlicher Verlust Maximaler Warteschlangenfüllstand und Verlustzählung
Nicht authentifizierter oder nicht autorisierter Client Konfiguration bei falscher Sicherheitsstufe angenommen Erwarteter Fehler und unveränderte Konfiguration

Bleibt der Datenstrom aus, prüfen Sie nacheinander Notify-Eigenschaft, Abonnementabschluss, Berechtigungen und Aktivität der Datenquelle. Sind Werte unplausibel, vergleichen Sie zuerst Rohbytes mit Vorzeichen, Skalierung und Byte-Reihenfolge, bevor Sie Funkparameter anpassen. Scheitern nur aktualisierte Geräte, untersuchen Sie zunächst Datenbank-Cache und Formatverhandlung.

Eine prüfbare Integrationsbeschreibung vorbereiten

Bringen Sie UUID-Register, Paketspezifikation, Referenzvektoren, Liste unterstützter Telefone und Betriebssysteme sowie die Kompatibilitätsmatrix zur Firmware-Prüfung mit. Obeitas Service für Firmware- und BSP-Diagnose bietet einen passenden Einstieg. Die Fallbeschreibung des ausgelieferten WS63-Funkmodulprojekts zeigt den Kontext für die Festlegung von Hardware und Funkbetriebsart; sie belegt nicht, dass dieser beispielhafte GATT-Vertrag auf dem Modul implementiert oder validiert wurde.

Ähnliche Beiträge