Zielgruppe: Mobile-App-Entwickler, Embedded-Firmware-Leitende und SDK-Eigentümer auf Markenseite, die das BLE-GATT-Schema eines Lesestifts in ihre Host-Anwendung integrieren müssen und verstehen wollen, welche Characteristics vom SIG übernommene 16-Bit-UUIDs (interop-fähig) und welche herstellerdefinierte 128-Bit-UUIDs (proprietär) sind und wie sich das Schema zwischen Firmware-Revisionen weiterentwickelt, ohne bestehende Apps im Feld zu brechen.
Jeder Lesestift, der seit 2023 aus unseren beiden Fabriken ausgeliefert wird, hat die gleiche BLE-Service-Signatur angekündigt: eine vom SIG übernommene 16-Bit-Human-Interface-Device-Service-UUID 0x1812 sowie eine herstellerdefinierte 128-Bit-Service-UUID, mit der die Host-App den Stift als Smart-Reading-Pen-Gerät erkennt. Innerhalb dieser Services sitzen 11 Characteristics, von denen 6 vom SIG übernommen und 5 herstellerdefiniert sind. Die gesamte GATT-Datenbank belegt 1,8 KB ROM auf der Q6/Q8-Firmware 3.3.1 und 1,4 KB auf der F8-Firmware 3.1.2.
Dieser Artikel geht jede UUID im Schema durch, erklärt, warum jede vom SIG übernommen oder herstellerdefiniert ist, und dokumentiert die Regeln, nach denen wir das Schema für einen neuen OEM-Kunden erweitern, damit die bestehenden 230+ Distributor-Apps nicht brechen.
1. Warum ein GATT-Schema überhaupt wichtig ist
Ein BLE-Peripheriegerät ohne dokumentiertes GATT-Schema ist eine Blackbox. Die Host-App muss raten, welche Characteristic was tut. In der Unterhaltungselektronikbranche ist das die häufigste Ursache für Tickets vom Typ „die App findet den Stift nicht“. Über unsere 47.000+ ausgelieferten Geräte hinweg sind die schema-bezogenen Tickets von 4,2 % aller Tickets im Jahr 2023 auf 0,7 % im Jahr 2026 gesunken, vor allem weil wir jetzt ein eingefrorenes Schema mit versionierten Erweiterungen ausliefern.
Das Schema, das wir auf der Q6/Q8-Firmware 3.3.1 verwenden, ist GATT-Schema v3.0, zuletzt überarbeitet im November 2025. Das vorherige v2.x-Schema wurde auf der K7/KF1-Firmware 1.9.5 ausgeliefert. Apps, die gegen v2.x geschrieben wurden, funktionieren weiterhin gegen v3.0, weil wir Characteristics nur hinzufügen, niemals entfernen und niemals die UUID einer Characteristic ändern.
2. Das Top-Level-Service-Layout
Der Stift kündigt in seiner Primary-Service-Liste drei Dienste an:
| Service | UUID | Typ | Erforderlich |
|---|---|---|---|
| Generic Access | 0x1800 | SIG 16-Bit | Ja |
| Generic Attribute | 0x1801 | SIG 16-Bit | Ja |
| Human Interface Device | 0x1812 | SIG 16-Bit | Ja |
| Smart Reading Pen Vendor Service | 8E0C0001-7B3C-4F8E-9F4D-2C8B5A1E0001 | Vendor 128-Bit | Ja |
| Battery Service | 0x180F | SIG 16-Bit | Ja |
| Device Information | 0x180A | SIG 16-Bit | Ja |
Generic Access (0x1800) und Generic Attribute (0x1801) sind auf jedem BLE-Peripheriegerät obligatorisch. Sie legen den Gerätenamen, das Erscheinungsbild und die Service-Change-Indikation offen. Human Interface Device (0x1812) ist der HOGP-Service, der die OID-Tap-Reports überträgt. Der Vendor Service ist der Ort, an dem unsere proprietären Characteristics leben. Battery (0x180F) und Device Information (0x180A) sind vom SIG übernommene Standarddienste, die jede Host-Plattform erwartet.
Der Stift kündigt die vollständige Primary-Service-Liste in einem einzelnen AD-Paket an, wenn die MTU dies zulässt. Auf F8 (BLE 5.1, MTU 247) passen alle sechs. Auf älteren K7/KF1-Funkmodulen (MTU 23) passen nur zwei in das AD-Paket, der Rest wird vom Host per Service Discovery ermittelt.
3. Die Characteristics des HID-Service (0x1812)
Der HID-Service legt sechs Characteristics offen:
| Characteristic | UUID | Eigenschaften | Hinweise |
|---|---|---|---|
| HID Information | 0x2A4A | Read | bcdHID, bCountryCode, Flags |
| Report Map | 0x2A4B | Read | Der Descriptor-Blob aus TC-058 |
| Protocol Mode | 0x2A4E | Read, Write | Report vs. Boot |
| HID Control Point | 0x2A4C | WriteWithoutResponse | Suspend / Resume |
| Report (Referenz 1) | 0x2A4D | Notify, Write, WriteWithoutResponse | OID-Tipp-Report |
| Report (Referenz 2) | 0x2A4D | Notify | Audio-VU-Meter |
Die einzelne UUID 0x2A4D wird für zwei Reports wiederverwendet, da der HID-Dienst mehrere Report-Charakteristiken erlaubt, die durch ihren Report-Reference-Deskriptor identifiziert werden. Beim Q6/Q8 verwenden wir zwei Report-Charakteristiken: Die erste ist der in TC-058 beschriebene OID-Tipp-Report, die zweite ist ein Audio-VU-Meter (von der Host-App verwendet, um während der TTS-Wiedergabe eine kleine VU-Anzeige darzustellen).
4. Die Characteristics des Vendor-Dienstes
Die UUID des Vendor-Dienstes lautet 8E0C0001-7B3C-4F8E-9F4D-2C8B5A1E0001. Die 128-Bit-UUID wurde mittels SHA-1 über unseren Firmennamen und einem festen Präfix erzeugt. Innerhalb des Vendor-Dienstes befinden sich fünf Characteristics:
| Characteristic | UUID | Properties | Zweck |
|---|---|---|---|
| Brand ID | 8E0C0002-7B3C-4F8E-9F4D-2C8B5A1E0001 | Read | Eingefrorene 4-Byte-Markenkennung |
| Wörterbuchstatus | 8E0C0003-7B3C-4F8E-9F4D-2C8B5A1E0001 | Read, Notify | Aktuell geladenes Sprachpaket |
| Audio Control | 8E0C0004-7B3C-4F8E-9F4D-2C8B5A1E0001 | Write | Lautstärke, Stummschaltung, EQ-Preset |
| Telemetry | 8E0C0005-7B3C-4F8E-9F4D-2C8B5A1E0001 | Notify, Indicate | Protokolle, Fehlercodes |
| OTA Control | 8E0C0006-7B3C-4F8E-9F4D-2C8B5A1E0001 | Write, Indicate | Auslöser für Firmware-Update |
Jede Characteristic folgt der SIG-Konvention: Eine 128-Bit-UUID mit gemeinsamem Präfix (8E0C0000-7B3C-4F8E-9F4D-2C8B5A1E0000) und einer 16-Bit-Instance-ID. Die letzten 4 Bytes der Instance-ID kodieren die Characteristic-Nummer. Dadurch lassen sich die UUIDs in einer BLE-Scanner-App visuell leicht scannen.
5. Der Battery Service (0x180F)
Der Battery Service stellt eine einzelne Characteristic bereit:
| Characteristic | UUID | Properties | Zweck |
|---|---|---|---|
| Battery Level | 0x2A19 | Read, Notify | 0–100 % Ladung |
Der Stift überträgt den Batteriestand auf Q6/Q8-Firmware 3.3.1 mit 1 Hz. Der ADC-Sample wird über 4 Samples gemittelt, um Rauschen zu entfernen. Eine Änderung von mehr als 5 % löst ein sofortiges Notify aus; kleinere Deltas werden im periodischen 1-Hz-Notify gebündelt. Die Host-App kann auch einen manuellen Read auslösen.
Ein subtiler Punkt: Der Wert der Battery Characteristic wird gemäß SIG-Spezifikation in Prozent angegeben, nicht in Millivolt. Millivolt-Messwerte werden über eine separate Vendor-Characteristic 8E0C0010-7B3C-4F8E-9F4D-2C8B5A1E0001 für Engineering-Diagnosen bereitgestellt.
6. Der Device Information Service (0x180A)
Der Device Information Service stellt Folgendes bereit:
| Characteristic | UUID | Properties | Wert bei Q6/Q8 |
|---|---|---|---|
| Manufacturer Name | 0x2A29 | Read | "Smart Reading Pen Mfg Co." |
| Modellnummer | 0x2A24 | Lesen | "Q8" |
| Seriennummer | 0x2A25 | Lesen | 12-stellige ASCII pro Einheit |
| Hardware-Version | 0x2A26 | Lesen | "Rev. D" |
| Firmware-Version | 0x2A26 | Lesen | "3.3.1" |
| Software-Version | 0x2A28 | Lesen | "Build 8642" |
| System-ID | 0x2A23 | Lesen | OUI + UUID pro Einheit |
Das Merkmal Modellnummer wird von der Host-App verwendet, um die korrekte Benutzeroberflächen-Vorlage zu laden. Wir geben hier keine personenbezogenen Daten an (keine MAC-Adresse in der System-ID; die System-ID besteht aus der OUI des Unternehmens plus der zufälligen UUID pro Einheit).
7. Der Erkennungsprozess, den die Host-App befolgen sollte
Eine korrekt arbeitende Host-App folgt dieser Reihenfolge:
- Scannen nach einem Werbepaket, das 0x1812 in der Liste der Service-UUIDs enthält.
- Verbinden mit 15 ms Verbindungsintervall, 0 ms Slave-Latenz, 4 s Überwachungszeitlimit.
- MTU-Austausch anfordern; bis zu 247 akzeptieren.
- Alle Primärdienste ermitteln.
- Für jeden Dienst alle Merkmale ermitteln.
- Für jedes Merkmal den Descriptor Characteristic Presentation Format lesen.
- Benachrichtigungen auf 0x2A4D (OID-Tipp) und 8E0C0005 (Telemetrie) abonnieren.
- Batteriestand (0x2A19) und Geräteinformationen lesen.
Eine fehlerhaft arbeitende App verbindet sich mit Standardparametern und versucht sofort zu schreiben. Dies beobachten wir bei 14 % der Host-Apps von Drittanbietern. Die Folge ist, dass die Verbindung etwa 3 s statt etwa 300 ms zur Stabilisierung benötigt. Unser QA-Scoring belohnt Apps, die den Ablauf einhalten.
8. Die Schema-Erweiterungsrichtlinie
Wir erweitern das GATT-Schema nach drei Regeln:
- Niemals ein Merkmal löschen. Sobald eine UUID in einer Produktions-Firmware ausgeliefert wird, bleibt diese UUID für die gesamte Lebensdauer der Plattform im Schema. Alte Apps lesen sie weiterhin und ignorieren den Wert.
- Niemals eine UUID ändern. Die UUID ist eine 128-Bit-Identität. Eine Änderung würde jede App beschädigen, die sie gespeichert hat.
- Neue Merkmale zur nächsten freien Instanz-ID hinzufügen. Der Herstellerdienst verfügt über 256 reservierte Instanz-IDs (0x0001 bis 0x0100). Wenn wir ein neues Merkmal hinzufügen, wählen wir die nächste freie ID und erhöhen die Nebenversion des Schemas.
Schema v3.0 (aktuell) verwendet die Instanz-IDs 0x0001 bis 0x0010. Schema v4.0 (geplant für L5-Firmware 4.3.0) wird die Instanz-IDs 0x0011 bis 0x0020 für neue Merkmale im Zusammenhang mit Classroom-Mode-Telemetrie verwenden.
9. Leistung: Erkennungszeit
| Schritt | Zeit bei Q6/Q8 | Zeit bei F8 | Zeit bei K7/KF1 |
|---|---|---|---|
| Verbindung zum ersten Dienst | 95 ms | 110 ms | 145 ms |
| Alle Dienste ermittelt | 280 ms | 330 ms | 520 ms |
| Alle Merkmale ermittelt | 410 ms | 490 ms | 880 ms |
| CCCD-Deskriptoren gelesen | 220 ms | 280 ms | 480 ms |
| MTU-Austausch | 38 ms | 42 ms | 65 ms |
| Gesamt erstes Paar | 1,04 s | 1,25 s | 2,1 s |
Eine Host-App, die all das in unter 1 s erledigt, gilt als „schnell“; 1,5 s ist „normal“; über 2 s ist „schlecht“. Unsere 38 hauseigenen Referenz-Apps für iOS/Android/Windows liegen alle unter 1,5 s.
10. Der Schema-Unterschied zwischen den Modellen
| Merkmal | Q6/Q8 | F8 | K7/KF1 | L5 | T2/Y6 | P2 |
|---|---|---|---|---|---|---|
| HID 0x2A4D (OID) | Ja | Ja | Ja | Ja | Ja | Ja |
| HID 0x2A4D (VU) | Ja | Nein | Nein | Ja | Ja | Nein |
| Batterie 0x2A19 | Ja | Ja | Ja | Ja | Ja | Ja |
| Marken-ID 8E0C0002 | Ja | Ja | Ja | Ja | Ja | Ja |
| Wörterbuchstatus 8E0C0003 | Ja | Ja | Ja | Ja | Ja | Ja |
| Audioregler 8E0C0004 | Ja | Nein | Nein | Ja | Ja | Nein |
| Telemetrie 8E0C0005 | Ja | Ja | Ja | Ja | Ja | Ja |
| OTA-Steuerung 8E0C0006 | Ja | Ja | Ja | Ja | Ja | Ja |
| Hersteller-Audio VU 8E0C0007 | Ja | Nein | Nein | Ja | Ja | Nein |
| Hersteller-Testmodus 8E0C0008 | Ja | Ja | Nein | Ja | Ja | Nein |
| Hersteller-Klassenraum-Modus 8E0C0009 | Nein | Nein | Nein | Ja | Ja | Nein |
Die Modelle L5, T2 und Y6 sind die einzigen Modelle, die über die Merkmale des Klassenraum-Modus verfügen, da diese Modelle in den Bildungskanal verkauft werden. Der K7/KF1 ist ein Heimstift für Einzelbenutzer, daher fehlen die Merkmale für den Klassenraum.
11. Die Schema-Unterschiede zwischen den Firmware-Versionen
| Firmware | Schema-Version | Hinzufügen | Entfernen | Kompatibel mit |
|---|---|---|---|---|
| K7 1.9.0 | 2.0 | — | — | Schema 2.0 |
| K7 1.9.5 | 2.1 | 8E0C0006 OTA | — | Schema 2.0, 2.1 |
| F8 3.1.0 | 2.5 | 8E0C0007 VU | — | Schema 2.5 |
| F8 3.1.2 | 2.5.1 | — | — | Schema 2.5 |
| Q6/Q8 3.3.0 | 3.0 | 8E0C0008 Test | — | Schema 3.0 |
| Q6/Q8 3.3.1 | 3.0 | — | — | Schema 3.0 |
| L5 4.2.0 | 3.1 | 8E0C0009 Classroom | — | Schema 3.1 |
| T2/Y6 2.6.4 | 3.1 | — | — | Schema 3.1 |
Das Schema ist abwärtskompatibel: Eine App, die für Schema 2.0 entwickelt wurde, kann sich mit einem Stift verbinden, der die Firmware Schema 3.1 ausführt, und alle Characteristics von Schema 2.0 lesen; die neuen werden einfach übersprungen.
12. Zuweisen von markenspezifischen UUIDs
Ein ODM-Kunde kann markenspezifische Characteristics anfragen. Wir vergeben aus dem Bereich 0x0100 bis 0x01FF. Der Kunde wählt 16 Instance-IDs aus diesem Bereich, und wir registrieren sie im GATT-Schema-Manifest. Das Manifest ist eine YAML-Datei im Firmware-Repository; es listet alle Instance-IDs, den Characteristic-Namen, die Eigenschaftsmaske, die Größe und den Initialwert auf. Die CI schlägt fehl, wenn zwei Kunden dieselbe Instance-ID anfordern.
Das Manifest für Q6/Q8-Firmware 3.3.1 listet 38 derzeit vergebene markenspezifische Bereiche. Wir können noch 13 weitere aufnehmen, bevor der Bereich 0x0100 bis 0x01FF erschöpft ist und wir auf 0x0200 erweitern müssen.
13. Der GATT-Datenbank-Komprimierungstrick
Eine GATT-Datenbank lässt sich in einen 1,8 KB großen Blob im ROM packen. Das von uns verwendete Format:
[uint16 service_count]
for each service:
[uint16 service_uuid_type] [128-bit UUID]
[uint16 characteristic_count]
for each characteristic:
[uint16 char_uuid_type] [128-bit UUID]
[uint8 properties]
[uint8 value_size]
[uint8 descriptor_count]
for each descriptor:
[uint16 desc_uuid_type] [128-bit UUID]
[uint8 payload_size] [payload]
Der Blob wird zur Firmware-Build-Zeit von einem Python-Skript generiert, das das YAML-Manifest liest. Die gesamten ROM-Kosten betragen 1.824 Bytes bei Q6/Q8-Firmware 3.3.1. F8 spart 384 Bytes, indem der HID-Service auf 5 statt 6 Characteristics reduziert wird (kein Audio VU).
14. Validierungssuite, die wir für jedes Schema ausführen
| Check | Tool | Prüfkriterium |
|---|---|---|
| UUID-Eindeutigkeit | Python-CI-Skript | Keine doppelten UUIDs im Manifest |
| Schema-Zukunftskompatibilität | Custom-Python-Harness | Schema N+1 lässt sich als Schema N parsen |
| Erkennungszeit | Saleae + Wireshark | Unter 1,5 s bei Q6/Q8 |
| Benachrichtigungsrate Batterie | Logikanalysator | Genau 1 Hz ±5 % |
| OTA-Charakteristik | CI-Skript | OTA-Charakteristik in allen Produktions-Firmware-Versionen vorhanden |
Ein Schema, das eine dieser Prüfungen nicht besteht, wird abgelehnt. Bei 86 Firmware-Releases seit 2023 wurden 4 an dieser Schleuse abgelehnt.
16. Weiterführende Literatur
- Reading Pen USB HID und HID over GATT
- Reading Pen HID-Report-Deskriptor und Usage Page
- Reading Pen Bluetooth-Pairing SSP Secure Simple Pairing
- Reading Pen GATT-Server und Benachrichtigungsmechanismus
- Reading Pen Bluetooth 5.0 vs. 5.2 vs. 5.3
- Reading Pen OTA-Firmware-Update-Mechanismus
- Reading Pen Telemetrie-Samplingrate
- Reading Pen Kryptografie und TrustZone