Odbiorcy: Deweloperzy aplikacji mobilnych, liderzy firmware'u wbudowanego oraz właściciele SDK po stronie marki, którzy muszą zintegrować schemat BLE GATT pióra do czytania ze swoją aplikacją hosta i którzy potrzebują zrozumieć, które charakterystyki są przyjętymi przez SIG 16-bitowymi UUID (gotowymi do interoperacyjności) w porównaniu z zdefiniowanymi przez producenta 128-bitowymi UUID (proprietary), a także jak schemat ewoluuje między wersjami firmware'u bez psucia działających aplikacji w terenie.
Każde pióro do czytania, które opuszcza nasze dwie fabryki od 2023 roku, reklamuje tę samą sygnaturę usługi BLE: 16-bitowy UUID usługi Human Interface Device przyjęty przez SIG 0x1812 oraz zdefiniowany przez producenta 128-bitowy UUID usługi, którego aplikacja hosta używa do identyfikacji pióra jako urządzenia marki Smart Reading Pen. Wewnątrz tych usług znajduje się 11 charakterystyk, z czego 6 jest przyjętych przez SIG, a 5 zdefiniowanych przez producenta. Cała baza danych GATT zajmuje 1,8 KB ROM w firmware Q6/Q8 3.3.1 oraz 1,4 KB w firmware F8 3.1.2.
Ten artykuł przeprowadza przez każdy UUID w schemacie, wyjaśnia, dlaczego każdy z nich jest przyjęty przez SIG lub zdefiniowany przez producenta, oraz dokumentuje zasady, których przestrzegamy przy rozszerzaniu schematu dla nowego klienta OEM, tak aby istniejące aplikacje 230+ dystrybutorów nie zostały zepsute.
1. Dlaczego schemat GATT w ogóle ma znaczenie
Peripheral BLE bez udokumentowanego schematu GATT to czarna skrzynka. Aplikacja hosta musi zgadywać, która charakterystyka za co odpowiada. W branży elektroniki użytkowej jest to przyczyna nr 1 zgłoszeń typu „aplikacja nie widzi pióra". Wśród naszych 47 000+ wysłanych urządzeń zgłoszenia związane ze schematem spadły z 4,2% wszystkich zgłoszeń w 2023 roku do 0,7% w 2026 roku, głównie dlatego, że dostarczamy zamrożony schemat z wersjonowanymi rozszerzeniami.
Schemat, którego używamy w firmware Q6/Q8 3.3.1, to Schemat GATT v3.0, ostatnia rewizja 2025-11. Poprzedni schemat v2.x był dostarczany z firmware K7/KF1 1.9.5. Aplikacje napisane pod v2.x nadal działają pod v3.0, ponieważ tylko dodajemy charakterystyki, nigdy ich nie usuwamy i nigdy nie zmieniamy UUID żadnej charakterystyki.
2. Układ usług najwyższego poziomu
Pióro reklamuje trzy usługi na swojej liście usług podstawowych:
| Usługa | UUID | Typ | Wymagana |
|---|---|---|---|
| Generic Access | 0x1800 | SIG 16-bit | Tak |
| Generic Attribute | 0x1801 | SIG 16-bit | Tak |
| Human Interface Device | 0x1812 | SIG 16-bit | Tak |
| Usługa własna Smart Reading Pen | 8E0C0001-7B3C-4F8E-9F4D-2C8B5A1E0001 | Vendor 128-bit | Tak |
| Battery Service | 0x180F | SIG 16-bit | Tak |
| Device Information | 0x180A | SIG 16-bit | Tak |
Generic Access (0x1800) i Generic Attribute (0x1801) są obowiązkowe na każdym peripheral BLE. Udostępniają nazwę urządzenia, appearance oraz wskazanie service-change. Human Interface Device (0x1812) to usługa HOGP przenosząca raporty kliknięć OID. Vendor Service to miejsce, w którym żyją nasze zastrzeżone charakterystyki. Battery (0x180F) i Device Information (0x180A) to standardowe usługi przyjęte przez SIG, których oczekuje każda platforma hosta.
Pióro reklamuje pełną listę usług podstawowych w jednym pakiecie AD, gdy pozwala na to MTU. Na F8 (BLE 5.1, MTU 247) mieścimy wszystkie sześć. Na starszych radiach K7/KF1 (MTU 23) mieścimy tylko dwie w pakiecie AD, a reszta jest wykrywana przez hosta za pomocą service discovery.
3. Charakterystyki usługi HID (0x1812)
Usługa HID udostępnia sześć charakterystyk:
| Charakterystyka | UUID | Właściwości | Uwagi |
|---|---|---|---|
| HID Information | 0x2A4A | Read | bcdHID, bCountryCode, flagi |
| Report Map | 0x2A4B | Read | Bloba deskryptora z TC-058 |
| Protocol Mode | 0x2A4E | Read, Write | Report vs Boot |
| HID Control Point | 0x2A4C | WriteWithoutResponse | Wstrzymaj / Wznów |
| Raport (odniesienie 1) | 0x2A4D | Notify, Write, WriteWithoutResponse | Raport dotknięcia OID |
| Raport (odniesienie 2) | 0x2A4D | Notify | Miernik VU audio |
Pojedynczy UUID 0x2A4D jest używany ponownie dla dwóch raportów, ponieważ usługa HID pozwala na wiele cech raportów identyfikowanych przez deskryptor Report Reference. W Q6/Q8 używamy dwóch cech raportów: pierwsza to raport dotknięcia OID opisany w TC-058, druga to miernik VU audio (używany przez aplikację hosta do wyświetlania małego wskaźnika VU podczas odtwarzania TTS).
4. Charakterystyki usługi dostawcy
UUID usługi dostawcy to 8E0C0001-7B3C-4F8E-9F4D-2C8B5A1E0001. 128-bitowy UUID został wygenerowany przy użyciu SHA-1 na nazwie naszej firmy i stałym prefiksie. Wewnątrz usługi dostawcy znajduje się pięć cech:
| Cecha | UUID | Właściwości | Przeznaczenie |
|---|---|---|---|
| Identyfikator marki | 8E0C0002-7B3C-4F8E-9F4D-2C8B5A1E0001 | Odczyt | Zamrożony 4-bajtowy identyfikator marki |
| Status słownika | 8E0C0003-7B3C-4F8E-9F4D-2C8B5A1E0001 | Odczyt, Powiadamianie | Aktualnie załadowany pakiet językowy |
| Sterowanie audio | Miernik VU audio | Zapis | Głośność, wyciszenie, ustawienie EQ |
| Telemetria | 8E0C0005-7B3C-4F8E-9F4D-2C8B5A1E0001 | Powiadamianie, Wskazywanie | Logi, kody błędów |
| Sterowanie OTA | 8E0C0006-7B3C-4F8E-9F4D-2C8B5A1E0001 | Zapis, Wskazywanie | Wyzwalacz aktualizacji oprogramowania |
Każda cecha jest zgodna z konwencją SIG: 128-bitowy UUID ze wspólnym prefiksem (8E0C0000-7B3C-4F8E-9F4D-2C8B5A1E0000) i 16-bitowym identyfikatorem instancji. Ostatnie 4 bajty identyfikatora instancji kodują numer cechy. Dzięki temu UUID-y są wizualnie łatwe do skanowania w aplikacji skanera BLE.
5. Usługa baterii (0x180F)
Usługa baterii udostępnia pojedynczą cechę:
| Cecha | UUID | Właściwości | Przeznaczenie |
|---|---|---|---|
| Poziom baterii | 0x2A19 | Odczyt, Powiadamianie | 0–100% naładowania |
Pióro rozgłasza poziom baterii z częstotliwością 1 Hz w oprogramowaniu Q6/Q8 3.3.1. Próbka ADC jest uśredniana z 4 próbek w celu usunięcia szumu. Zmiana o więcej niż 5% wyzwala natychmiastowe powiadomienie; mniejsze zmiany są grupowane w okresowe powiadomienie 1 Hz. Aplikacja hosta może również wykonać ręczny odczyt.
Subtelny punkt: wartość cechy baterii jest wyrażona w procentach, a nie w miliwoltach, zgodnie ze specyfikacją SIG. Odczyty w miliwoltach są udostępniane za pośrednictwem oddzielnej cechy dostawcy 8E0C0010-7B3C-4F8E-9F4D-2C8B5A1E0001 do celów diagnostyki inżynieryjnej.
6. Usługa informacji o urządzeniu (0x180A)
Usługa informacji o urządzeniu udostępnia:
| Cecha | UUID | Właściwości | Wartość w Q6/Q8 |
|---|---|---|---|
| Nazwa producenta | 0x2A29 | Odczyt | "Smart Reading Pen Mfg Co." |
| Numer modelu | 0x2A24 | Odczyt | "Q8" |
| Numer seryjny | 0x2A25 | Odczyt | 12-znakowy ASCII na jednostkę |
| Wersja sprzętu | 0x2A26 | Odczyt | "Rev. D" |
| Wersja oprogramowania sprzętowego | 0x2A26 | Odczyt | "3.3.1" |
| Wersja oprogramowania | 0x2A28 | Odczyt | "Build 8642" |
| Identyfikator systemu | 0x2A23 | Odczyt | OUI + losowy UUID na jednostkę |
Charakterystyka Numer modelu jest używana przez aplikację hosta do wczytania odpowiedniej skórki interfejsu. Nie umieszczamy tu danych osobowych (brak adresu MAC w Identyfikatorze systemu; Identyfikator systemu to OUI firmy plus losowy UUID na jednostkę).
7. Procedura wykrywania, którą powinna stosować aplikacja hosta
Dobrze napisana aplikacja hosta stosuje następującą sekwencję:
- Skanuj pakiet rozgłoszeniowy zawierający 0x1812 na liście UUID usług.
- Połącz z interwałem połączenia 15 ms, opóźnieniem slave 0 ms, limitem nadzoru 4 s.
- Poproś o wymianę MTU; akceptuj do 247.
- Wykryj wszystkie usługi główne.
- Dla każdej usługi wykryj wszystkie charakterystyki.
- Dla każdej charakterystyki odczytaj deskryptor Characteristic Presentation Format.
- Subskrybuj powiadomienia na 0x2A4D (dotknięcie OID) oraz 8E0C0005 (telemetria).
- Odczytaj poziom baterii (0x2A19) oraz informacje o urządzeniu.
Źle napisana aplikacja łączy się z domyślnymi parametrami i natychmiast próbuje zapisywać. Widzimy to w 14% aplikacji hosta pierwszej strony. Skutkiem jest to, że połączenie trwa ~3 s zamiast ~300 ms. Nasza ocena QA nagradza aplikacje stosujące tę procedurę.
8. Polityka rozszerzania schematu
Schemat GATT rozszerzamy według trzech zasad:
- Nigdy nie usuwaj charakterystyki. Gdy UUID trafi do produkcyjnego firmware, pozostaje w schemacie przez cały okres życia platformy. Stare aplikacje nadal go odczytują i ignorują wartość.
- Nigdy nie zmieniaj UUID. UUID to 128-bitowa tożsamość. Jego zmiana psuje każdą aplikację, która go zapisała.
- Dodawaj nowe charakterystyki pod następnym wolnym identyfikatorem instancji. Usługa dostawcy ma zarezerwowane 256 identyfikatorów instancji (od 0x0001 do 0x0100). Gdy dodajemy nową charakterystykę, wybieramy następny wolny i zwiększamy wersję minor schematu.
Schemat v3.0 (bieżący) używa identyfikatorów instancji od 0x0001 do 0x0010. Schemat v4.0 (planowany dla firmware L5 4.3.0) użyje identyfikatorów instancji od 0x0011 do 0x0020 dla nowych charakterystyk związanych z telemetrią trybu klasowego.
9. Wydajność: czas wykrywania
| Krok | Czas w Q6/Q8 | Czas w F8 | Czas w K7/KF1 |
|---|---|---|---|
| Połączenie z pierwszą usługą | 95 ms | 110 ms | 145 ms |
| Wszystkie usługi wykryte | 280 ms | 330 ms | 520 ms |
| Wszystkie charakterystyki wykryte | 410 ms | 490 ms | 880 ms |
| Odczyt deskryptorów CCCD | 220 ms | 280 ms | 480 ms |
| Wymiana MTU | 38 ms | 42 ms | 65 ms |
| Łącznie pierwsza para | 1,04 s | 1,25 s | 2,1 s |
Aplikacja hosta, która wykonuje to wszystko w czasie poniżej 1 s, jest „szybka”; 1,5 s to „norma”; powyżej 2 s to „słabo”. Wszystkie nasze 38 wewnętrznych aplikacji referencyjnych na iOS/Android/Windows osiągają wynik poniżej 1,5 s.
10. Różnice schematu między modelami
| Cecha | Q6/Q8 | F8 | K7/KF1 | L5 | T2/Y6 | P2 |
|---|---|---|---|---|---|---|
| HID 0x2A4D (OID) | Tak | Tak | Tak | Tak | Tak | Tak |
| HID 0x2A4D (VU) | Tak | Nie | Nie | Tak | Tak | Nie |
| Bateria 0x2A19 | Tak | Tak | Tak | Tak | Tak | Tak |
| Brand ID 8E0C0002 | Tak | Tak | Tak | Tak | Tak | Tak |
| Status słownika 8E0C0003 | Tak | Tak | Tak | Tak | Tak | Tak |
| Sterowanie audio 8E0C0004 | Tak | Nie | Nie | Tak | Tak | Nie |
| Telemetria 8E0C0005 | Tak | Tak | Tak | Tak | Tak | Tak |
| Sterowanie OTA 8E0C0006 | Tak | Tak | Tak | Tak | Tak | Tak |
| Dźwięk dostawcy VU 8E0C0007 | Tak | Nie | Nie | Tak | Tak | Nie |
| Tryb testowy dostawcy 8E0C0008 | Tak | Tak | Nie | Tak | Tak | Nie |
| Tryb klasowy dostawcy 8E0C0009 | Nie | Nie | Nie | Tak | Tak | Nie |
Modele L5, T2 i Y6 to jedyne, które posiadają cechy trybu kinałów, ponieważ są to modele sprzedawane do kanału edukacyjnego. K7/KF1 to pióro domowe dla jednego użytkownika, więc cechy kanałowe są nieobecne.
11. Różnice schematu między wersjami oprogramowania sprzętowego
| Oprogramowanie | Wersja schematu | Dodaj | Usuń | Kompatybilny z |
|---|---|---|---|---|
| K7 1.9.0 | 2.0 | — | — | Schemat 2.0 |
| K7 1.9.5 | 2.1 | 8E0C0006 OTA | — | Schemat 2.0, 2.1 |
| F8 3.1.0 | 2.5 | 8E0C0007 VU | — | Schemat 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 |
Schemat jest kompatybilny w przód: aplikacja napisana dla Schema 2.0 może połączyć się z piórem pracującym na firmware Schema 3.1 i odczytać wszystkie cechy Schema 2.0; po prostu pominie nowe.
12. Jak alokować UUID specyficzne dla marki
Klient ODM może poprosić o cechy specyficzne dla marki. Alokujemy je z zakresu od 0x0100 do 0x01FF. Klient wybiera 16 identyfikatorów instancji z tego zakresu, a my rejestrujemy je w manifeście schematu GATT. Manifest to plik YAML w repozytorium firmware; zawiera listę wszystkich identyfikatorów instancji, nazwę cechy, maskę właściwości, rozmiar oraz wartość początkową. CI zgłasza błąd, jeśli dwóch klientów poprosi o ten sam identyfikator instancji.
Manifest dla firmware Q6/Q8 3.3.1 zawiera 38 aktualnie przydzielonych zakresów specyficznych dla marki. Możemy przyjąć jeszcze 13, zanim wyczerpie się zakres od 0x0100 do 0x01FF i będziemy musieli rozszerzyć go do 0x0200.
13. Sztuczka z kompresją bazy danych GATT
Bazę danych GATT można spłaszczyć do bloba 1,8 KB w ROM-ie. Format, którego używamy:
[uint16 service_count]
dla każdej usługi:
[uint16 service_uuid_type] [128-bit UUID]
[uint16 characteristic_count]
dla każdej cechy:
[uint16 char_uuid_type] [128-bit UUID]
[uint8 properties]
[uint8 value_size]
[uint8 descriptor_count]
dla każdego deskryptora:
[uint16 desc_uuid_type] [128-bit UUID]
[uint8 payload_size] [payload]
Blob jest generowany w czasie budowania firmware przez skrypt Pythona, który odczytuje manifest YAML. Całkowity koszt w ROM-ie wynosi 1824 bajty na firmware Q6/Q8 3.3.1. F8 oszczędza 384 bajty, zwijając usługę HID do 5 cech zamiast 6 (bez Audio VU).
14. Pakiet walidacji uruchamiany dla każdego schematu
| Sprawdzenie | Narzędzie | Kryterium zaliczenia |
|---|---|---|
| Unikalność UUID | Skrypt CI w Pythonie | Brak zduplikowanych UUID w manifeście |
| Kompatybilność w przód schematu | Własny harness w Pythonie | Schema N+1 może być sparsowany jako Schema N |
| Czas wykrywania | Saleae + Wireshark | Poniżej 1,5 s na Q6/Q8 |
| Częstotliwość powiadomień o baterii | Analizator logiczny | Dokładnie 1 Hz ±5% |
| Cecha OTA | Skrypt CI | Cecha OTA obecna we wszystkich firmware produkcyjnych |
Schemat, który nie przejdzie którejkolwiek z tych kontroli, jest odrzucany. Spośród 86 wydań firmware od 2023 roku, 4 zostały odrzucone na tej bramce.
16. Powiązane lektury
- Reading Pen USB HID i HID przez GATT
- Reading Pen deskryptor raportu HID i strona użycia
- Reading Pen parowanie Bluetooth SSP Secure Simple Pairing
- Reading Pen serwer GATT i mechanizm powiadomień
- Reading Pen Bluetooth 5.0 vs 5.2 vs 5.3
- Reading Pen mechanizm aktualizacji OTA firmware
- Reading Pen częstotliwość próbkowania telemetrii
- Reading Pen kryptografia i TrustZone