Ostatnio pisałem Wam o Thingy:52. Ciekawa rzecz – ale ileż można patrzeć na aplikację w smartfonie? O ile programowanie samego Thingy może nie być takie łatwe, o tyle wykorzystywanie jego usług jest już stosunkowo proste. I jeszcze lepsza wiadomość: usługi Thingy można wykorzystać również na Raspberry Pi Zero W! W ten sam sposób, jak robi to aplikacja Nordic’a na Waszym smartfonie.
Poniżej zobaczymy, jak można dostać się do usług BLE Thingy. Nie macie Thingy:52? Nie przejmujcie się i czytajcie. Ta wiedza przyda Wam się, gdy tylko będziecie chcieli nawiązać połączenie i wykorzystać usługi dowolnego urządzenie komunikującego się przez BLE.
Więcej o Thingy:52: seria tekstów o Thingy.
Bluetooth Low Energy
Do całej zabawy przyda się kilka podstawowych informacji na temat Bluetooth Low Energy (BLE). Oczywiście każdy z Was wie, co to jest Bluetooth (BT). Ale dla pewności – Bluetooth to taki rodzaj połączenia radiowego w paśmie 2.4 GHz. Mniejsza o historię – bo ta była trochę wyboista. W tej chwili jest jednym z podstawowych sposobów łączenia urządzeń na krótki dystans. Wykorzystują go np. telefony do podłączenia słuchawek – albo wysyłania muzyki na domowy wzmacniacz.
Jak każdy interfejs tego typu, BT ewoluował. Z każdą nową wersją był szybszy, udostępniał nowe możliwości. W końcu powstała wersja 4.0 w której pojawił się Bluetooth Low Energy (zwany też Smart).
Wersje Bluetooth:
- BR: Basic Rate, 1Mb/s., 2001, v1.1
- EDR: enhanced rate, 2-3MBit, 2004, v2.0
- HS: high Speed, 2009, v3.0,
- LE: Low Energy, 2010, 4.0.
BLE jest trochę inny. To znaczy – to dalej interfejs radiowy oparty na tym samym paśmie, ale inaczej modulowany, odznaczający się za to znacznie niższym poborem energii i trybami pracy nie wymagającymi parowania. Co ważne: BLE nie jest kompatybilny z 'normalnym’ Bluetooth. Jeżeli macie telefon z Bluetooth – to wcale nie oznacza, że dogada się on z urządzeniami BLE. Wasz telefon może być zgodny z Bluetooth 4.x (4.1, 4.2 i tak dalej) – ale wcale nie z Bluetooth Low Energy. Upewnijcie się, czy Wasz telefon wspiera BLE zanim podejmiecie decyzje o kupnie tego typu akcesoriów.
Urządzenia BLE są zgodne z profilami. np. profil HID (Human Interface Device) opisuje np. myszki lub klawiatury. Profile określają jakiego typu jest urządzenie (aplikacja). Profile zawierają usługi (ang. service). Usługi to nic innego jak zbiory funkcji, które oferuje urządzenie, np. pomiary środowiskowe. Usługa zawiera z kolei zestaw charakterystyk (ang. characteristics). To one reprezentują konkretne wartości – np. temperatury i ciśnienia.
Usługi i charakterystyki identyfikowane są za pomocą UUID: uniwersalnego identyfikatora.
Dla przykładu, spójrzcie na stronę Thingy: BLE services.
Czytając po kolei:
-
- Base UUID: EF68xxxx-9B35-4933-9B10-52FFA9740042: to bazowy identyfikator UUID usług i charakterystyk Thingy. Wszystkie będą nazwane tak samo, z wyjątkiem części „xxxx”. Te cztery znaki będą różne dla każdej usługi i charakterystyki. Żeby się nie powtarzać, w dokumentacji znajdziecie tylko tą część.
- Thingy configuration service: 0100, usługa konfiguracji Thingy, jej cały UUID będzie więc: EF680100-9B35-4933-9B10-52FFA9740042
- Usługa konfiguracji zawiera charakterystykę: Device name characteristic: 0101 (a więc: EF680101-9B35-4933-9B10-52FFA9740042). Nazwa własna urządzenia jest szczególnie przydatna, jeżeli w otoczeniu znajduje się kilka urządzeń BLE (10 bajtów, czyli 10 znaków),
- Write/Read: oznacza, że z tej charakterystyki możecie odczytywać dane (read) – lub je zapisywać (write). Tutaj: nazwę egzemplarza Thingy możecie odczytać – ale również zapisać na samym urządzeniu. Możecie również spotkać się z charakterystykami Notify – do których się jakby rejestrujecie, a one – co określony czas raportują swoje wartości.
Przeglądnijcie ten dokument. Znajdziecie w nim wszystkie usługi oferowane przez Thingy. Poniżej krótkie zestawienie:
Usługa | UUID (część znacząca) | Funkcja | Charakterystyki |
---|---|---|---|
Thingy configuration service | 0100 | Ustawienia Thingy | Nazwa własna, wersja oprogramowani, parametry rozgłoszeniowe (powiadamianie o swojej aktywności), połączenia itp. |
Environment service | 0200 | Dane z czujników środowiskowych | Temperatura (0201), ciśnienie, wilgotność, kolor otoczenia |
User interface | 0300 | Interfejs użytkownika | Kolor diody RGB, stan przycisku |
Motion service | 0400 | Ruch i położenie | Kąty, nachylenie – ale i licznik kroków |
Sound Service | 0500 | Dźwięki | Status głośnika i mikrofonu |
Battery service | 180F | Zasilanie | Stan naładowania baterii |
DFU | FE59 | Uzupełnianie oprogramowania |
Już za chwilę nauczycie się z nich wszystkich korzystać:)
Przygotowanie Raspberry
Do dalszych doświadczeń konieczna będzie Raspberry Pi Zero W. Raspberry Pi 3 również wyposażono w moduł BLE – ale jej nie testowałem. Tutaj używam Zero W. Uwaga: mówię tu o wersji „W” – jednej z ostatnich. Wyposażono ją w moduł WiFi oraz Bluetooth z obsługą LE. „Zwykła” Zero takich rozszerzeń nie posiada. Oczywiście możecie podłączyć do USB moduł zgodny z BLE – i kontynuować dalszą zabawę.
Na Raspberry zainstalujcie Rasbiana. Ja używam wersji stretch-lite (2017-11-29-raspbian-stretch-lite). Włączcie Raspberry do domowej sieci, upewnijcie się, że możecie zalogować się do niej przez ssh. Możecie też podłączyć raspberry do monitora, dołączyć do niej klawiaturę i myszkę – a poniższe doświadczenia kontynuować na terminalu (konieczny będzie aktywny hub, bo Zero ma tylko jeden port USB).
Przygotowanie Thingy 52
Thingy nie trzeba jakoś specjalnie przygotowywać. Warto jednak najpierw naładować jego baterię i użyć ją choć raz ze smartfonem (aplikacja Nordic Thingy). Podczas pierwszego łączenia, nadacie Thingy nazwę własną. Aplikacja zapisze ją na samym module. W ten sposób łatwiej będzie zidentyfikować Wasze urządzenie. Swojego Thingy nazwałem 'cosik1′.
Zwróćcie też uwagę na naklejkę na samym Thingy. Zawiera ona 48-bitowy adres konkretnego urządzenia (jest unikalny dla każdej sztuki). U mnie to: E3:F2:CA:0B:88:1E.
Nieużywana Thingy, po kilku minutach przechodzi w stan uśpienia. Wtedy jej dioda przestaje pulsować na niebiesko. Wystarczy potrząsnąć Thingy (lub wcisnąć górny przycisk) – a „ożyje”. Thingy nie uśpi się, jeżeli połączenie będzie aktywne (dioda pulsuje na zielono). W trybie uśpienia nie można się z Thingy połączyć.
Narzędzie hcitool
Zalogujcie się do Raspberry poprzez ssh (albo otwórzcie terminal, jeżeli używacie Raspberry bezpośrednio). Wywołajcie narzędzie hcitool:
1 2 3 4 5 6 |
$ sudo hcitool lescan LE Scan ... 12:11:30:52:EC:8B (unknown) E3:F2:CA:0B:88:1E cosik1 E3:F2:CA:0B:88:20 (unknown) E3:F2:CA:0B:88:1E (unknown) |
hcitool to narzędzie, które umożliwia operacje na łączu bluetooth. Paramter „lescan” rozpoczyna skanowanie w poszukiwaniu urządzeń BLE (samo 'scan’ – urządzeń 'tradycyjnego’ Bluetooth).
Jak widać, hcitool znalazł mojego „cosik1” (i kilka innych urządzeń).
Narzędzie gatttool
Narzędzie gatttol pozwoli na dogadanie z usługami BLE. Uruchomcie je z adresem Waszego Thingy:
1 |
$ sudo gatttool -t random -b E3:F2:CA:0B:88:1E -I |
’-b’ pozwala na podanie adresu urządzenia BLE. ’-t’ ustawia typ adresu LE – i bez podania tego parametru, nie mogłem się do Thingy podłączyć. Rozwiązanie znalazłem na forum Nordic Dev-Zone.
Parametr ’-I’ oznacza tryb interaktywny.
1 2 |
$ sudo gatttool -t random -b E3:F2:CA:0B:88:1E -I [E3:F2:CA:0B:88:1E][LE]> |
Teraz wywołajcie polecenie „connect„:
1 2 3 4 |
[E3:F2:CA:0B:88:1E][LE]> connect Attempting to connect to E3:F2:CA:0B:88:1E Connection successful [E3:F2:CA:0B:88:1E][LE]> |
Program wróci do trybu interakcyjnego, ale po chwili powinien poinformować o uzyskaniu połączenia. Adres w znaku zachęty będzie podświetlony. Zauważcie, że dioda na Thingy zacznie opalizować na zielono.
Czas na uzyskanie informacji o dostępnych usługach: polecenie „primary„:
1 2 3 4 5 6 7 8 9 10 |
[E3:F2:CA:0B:88:1E][LE]> primary attr handle: 0x0001, end grp handle: 0x0009 uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle: 0x000a, end grp handle: 0x000d uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle: 0x000e, end grp handle: 0x001c uuid: ef680100-9b35-4933-9b10-52ffa9740042 attr handle: 0x001d, end grp handle: 0x002e uuid: ef680200-9b35-4933-9b10-52ffa9740042 attr handle: 0x002f, end grp handle: 0x004c uuid: ef680400-9b35-4933-9b10-52ffa9740042 attr handle: 0x004d, end grp handle: 0x0054 uuid: ef680300-9b35-4933-9b10-52ffa9740042 attr handle: 0x0055, end grp handle: 0x005f uuid: ef680500-9b35-4933-9b10-52ffa9740042 attr handle: 0x0060, end grp handle: 0x0063 uuid: 0000180f-0000-1000-8000-00805f9b34fb attr handle: 0x0064, end grp handle: 0xffff uuid: 0000fe59-0000-1000-8000-00805f9b34fb |
Zauważcie, że oprócz usług których uuid jest zgodny z „EF68xxxx-9B35-4933-9B10-52FFA9740042”, znalazło się kilka typu „00001800-0000-1000-8000-00805f9b34fb”. Usługi te biorą się ze specyfikacji samego BLE. Żeby być zgodnym ze standardem Bluetooth, urządzenia o danym profilu muszą implementować określone usługi „ogólne” – to właśnie te zaczynające się od 0000. Nie będę się tu nimi zajmował – ale działają w identyczny sposób jak te dostarczone przez Nordic’a.
Teraz sprawdzimy charakterystyki: polecenie „characteristics„. Wywołajcie je i poczekajcie chwilę:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
[E3:F2:CA:0B:88:1E][LE]> characteristics handle: 0x0002, char properties: 0x02, char value handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb handle: 0x0004, char properties: 0x02, char value handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb handle: 0x0006, char properties: 0x02, char value handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb handle: 0x0008, char properties: 0x02, char value handle: 0x0009, uuid: 00002aa6-0000-1000-8000-00805f9b34fb handle: 0x000b, char properties: 0x20, char value handle: 0x000c, uuid: 00002a05-0000-1000-8000-00805f9b34fb <strong>handle: 0x000f, char properties: 0x0a, char value handle: 0x0010, uuid: ef680101-9b35-4933-9b10-52ffa9740042</strong> handle: 0x0011, char properties: 0x0a, char value handle: 0x0012, uuid: ef680102-9b35-4933-9b10-52ffa9740042 handle: 0x0013, char properties: 0x0a, char value handle: 0x0014, uuid: ef680104-9b35-4933-9b10-52ffa9740042 handle: 0x0015, char properties: 0x0a, char value handle: 0x0016, uuid: ef680105-9b35-4933-9b10-52ffa9740042 handle: 0x0017, char properties: 0x0a, char value handle: 0x0018, uuid: ef680106-9b35-4933-9b10-52ffa9740042 handle: 0x0019, char properties: 0x02, char value handle: 0x001a, uuid: ef680107-9b35-4933-9b10-52ffa9740042 handle: 0x001b, char properties: 0x0a, char value handle: 0x001c, uuid: ef680108-9b35-4933-9b10-52ffa9740042 <strong>handle: 0x001e, char properties: 0x10, char value handle: 0x001f, uuid: ef680201-9b35-4933-9b10-52ffa9740042</strong> handle: 0x0021, char properties: 0x10, char value handle: 0x0022, uuid: ef680202-9b35-4933-9b10-52ffa9740042 handle: 0x0024, char properties: 0x10, char value handle: 0x0025, uuid: ef680203-9b35-4933-9b10-52ffa9740042 handle: 0x0027, char properties: 0x10, char value handle: 0x0028, uuid: ef680204-9b35-4933-9b10-52ffa9740042 handle: 0x002a, char properties: 0x10, char value handle: 0x002b, uuid: ef680205-9b35-4933-9b10-52ffa9740042 handle: 0x002d, char properties: 0x0a, char value handle: 0x002e, uuid: ef680206-9b35-4933-9b10-52ffa9740042 handle: 0x0030, char properties: 0x0a, char value handle: 0x0031, uuid: ef680401-9b35-4933-9b10-52ffa9740042 handle: 0x0032, char properties: 0x10, char value handle: 0x0033, uuid: ef680402-9b35-4933-9b10-52ffa9740042 handle: 0x0035, char properties: 0x10, char value handle: 0x0036, uuid: ef680403-9b35-4933-9b10-52ffa9740042 handle: 0x0038, char properties: 0x10, char value handle: 0x0039, uuid: ef680404-9b35-4933-9b10-52ffa9740042 handle: 0x003b, char properties: 0x10, char value handle: 0x003c, uuid: ef680405-9b35-4933-9b10-52ffa9740042 handle: 0x003e, char properties: 0x10, char value handle: 0x003f, uuid: ef680406-9b35-4933-9b10-52ffa9740042 handle: 0x0041, char properties: 0x10, char value handle: 0x0042, uuid: ef680407-9b35-4933-9b10-52ffa9740042 handle: 0x0044, char properties: 0x10, char value handle: 0x0045, uuid: ef680408-9b35-4933-9b10-52ffa9740042 handle: 0x0047, char properties: 0x10, char value handle: 0x0048, uuid: ef680409-9b35-4933-9b10-52ffa9740042 handle: 0x004a, char properties: 0x10, char value handle: 0x004b, uuid: ef68040a-9b35-4933-9b10-52ffa9740042 handle: 0x004e, char properties: 0x10, char value handle: 0x004f, uuid: ef680302-9b35-4933-9b10-52ffa9740042 handle: 0x0051, char properties: 0x0a, char value handle: 0x0052, uuid: ef680301-9b35-4933-9b10-52ffa9740042 handle: 0x0053, char properties: 0x0a, char value handle: 0x0054, uuid: ef680303-9b35-4933-9b10-52ffa9740042 handle: 0x0056, char properties: 0x0a, char value handle: 0x0057, uuid: ef680501-9b35-4933-9b10-52ffa9740042 handle: 0x0058, char properties: 0x04, char value handle: 0x0059, uuid: ef680502-9b35-4933-9b10-52ffa9740042 handle: 0x005a, char properties: 0x10, char value handle: 0x005b, uuid: ef680503-9b35-4933-9b10-52ffa9740042 handle: 0x005d, char properties: 0x10, char value handle: 0x005e, uuid: ef680504-9b35-4933-9b10-52ffa9740042 handle: 0x0061, char properties: 0x12, char value handle: 0x0062, uuid: 00002a19-0000-1000-8000-00805f9b34fb handle: 0x0065, char properties: 0x28, char value handle: 0x0066, uuid: 8ec90003-f315-4f60-9fb8-838830daea50 |
Lista jest całkiem pokaźna!
Nordic dostarcza całkiem pokaźną bibliotekę narzędzi Bluetooth pod Androida. Otwórzcie google play i poszukajcie: nRF Toolbox, nRF Connect, nRF Logger.
Charakterystyka charakterystyki:)
Każda z charakterystyk opisana jest następująco za pomocą kilku pól. Weźmy na przykład 0201:
1 |
handle: 0x000f, char properties: 0x0a, char value handle: 0x0010, uuid: ef680101-9b35-4933-9b10-52ffa9740042 |
Po kolei:
Parametr | Znaczenie |
handle: 0x000f | „Uchwyt” do charakterystyki, taki krótki identyfikator czy wskaźnik. Wywołując charakterystyki możecie używać UUID (przydługi) lub właśnie „handle” |
char properties: 0x0a | O tym poniżej… |
char value handle: 0x0010 | Uchwyt do wartości |
uuid: ef680101-9b35-4933-9b10-52ffa9740042 | Identyfikator UUID charakterystyki. Para UUID-handle jest unikalna. |
„char properties” – to własności wartości charakterystyki. Pole to jest ważne, ponieważ określa, co można zrobić z daną wartością. Niestety, trzeba je przetłumaczyć na bity. Tutaj: 0x0a = 0000 1010. Znaczenie poszczególnych bitów: (przykłady dla 0x0a i 0x10 – np. temperatura):
Znaczenie | Maska bitowa | Funkcja | 0x0a | 0x10 |
Broadcast | 0x01 | Wartość tej charakterystyki może być dodana do pakietów rozgłoszeniowych (advertisment) | 0 (nie) | 0 (nie) |
Read | 0x02 | Wartość może być odczytana | 1 (tak) | 0 (nie) |
Write without response | 0x04 | Wartość może być zapisana (bez konieczności potwierdzania) | 0 (nie) | 0 (nie) |
Write | 0x08 | Wartość może być zapisana; wynik będzie potwierdzony | 1 (tak) | 0 (nie) |
Notify | 0x10 | Wartość może być wysyłana przez urządzenie do klienta samoczynnie – w odstępach czasu określonych przez konfigurację | 0 (nie) | 1 (tak) |
Nazwa urządzenia
Zgodnie z dokumentacją Nordica, usługa 'Thingy configuration service’ ma adres 0x0100 (czyli EF680100-9B35-4933-9B10-52FFA9740042). Komenda gatttool „primary” zwróciła między innymi:
1 2 |
<strong>attr handle: 0x000e, end grp handle: 0x001c uuid: ef680100-9b35-4933-9b10-52ffa9740042</strong> attr handle: 0x001d, end grp handle: 0x002e uuid: ef680200-9b35-4933-9b10-52ffa9740042 |
Sprawdźmy deskryptory usługi – zaczynając od uchwytu 0x000e aż do następnej usługi – 0x0001d:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[E3:F2:CA:0B:88:1E][LE]> char-desc 0e 1d handle: 0x000e, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x000f, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0010, uuid: ef680101-9b35-4933-9b10-52ffa9740042 handle: 0x0011, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0012, uuid: ef680102-9b35-4933-9b10-52ffa9740042 handle: 0x0013, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0014, uuid: ef680104-9b35-4933-9b10-52ffa9740042 handle: 0x0015, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0016, uuid: ef680105-9b35-4933-9b10-52ffa9740042 handle: 0x0017, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0018, uuid: ef680106-9b35-4933-9b10-52ffa9740042 handle: 0x0019, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x001a, uuid: ef680107-9b35-4933-9b10-52ffa9740042 handle: 0x001b, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x001c, uuid: ef680108-9b35-4933-9b10-52ffa9740042 handle: 0x001d, uuid: 00002800-0000-1000-8000-00805f9b34fb |
Po kolei:
Uchwyt | UUID (początek) | Znaczenie |
0x000e | 00002800 | 2800 oznacza uchwyt do usługi |
0x000f | 00002803 | 2803 oznacza uchwyt do charakterystyki |
0x0010 | ef680101 | Uchwyt do wartości charakterystyki |
0x0011 | 00002803 | 2803 oznacza uchwyt do charakterystyki |
0x0012 | ef680102 | Uchwyt do wartości charakterystyki |
0x0013 | 00002803 | 2803 oznacza uchwyt do charakterystyki |
0x0014 | ef680103 | Uchwyt do wartości charakterystyki |
0x0015 | 00002803 | 2803 oznacza uchwyt do charakterystyki |
0x0016 | ef680104 | Uchwyt do wartości charakterystyki |
0x0017 | 00002803 | 2803 oznacza uchwyt do charakterystyki |
0x0018 | ef680105 | Uchwyt do wartości charakterystyki |
0x0019 | 00002803 | 2803 oznacza charakterystykę |
0x001a | ef680106 | Uchwyt do wartości charakterystyki |
0x001b | 00002803 | 2803 oznacza uchwyt do charakterystyki |
0x001c | ef680107 | Uchwyt do wartości charakterystyki |
0x001d | 00002800 | 2800 to identyfikator kolejnej usługi |
Widać stąd, że usługa 0100 ma siedem charakterystyk o identyfikatorach ef68010x.
Zwróćcie uwagę na sekwencję:
- Uchwyt usługi (UUID: 0x2800),
- Uchwyt charakterystyki (UUID: 0x2803),
- Wartość charakterystyki,
- Opcjonalnie: deskryptor charakterystyki CCCD (UUID: 0x2903)
- Uchwyt do kolejnej usługi…
Wracając do, nazwy urządzenia – zwraca ją charakterystyka „Device name characteristic” usługi „Thingy configuration service”. Zgodnie z dokumentacją Nordica:
Device name characteristic | 0101 | Write/Read | max 10 bytes | Device name as ASCII string. |
Zauważcie, że charakterystyka jest typu read/write: można z niej czytać lub do niej pisać. Zwraca maksymalnie 10 bajtów a zawiera – łańcuch znaków jako nazwę własną urządzenia.
Zgodnie z powyższymi ustaleniami, uchwyt do wartości charakterystyki 0101 (czyli EF680101-9B35-4933-9B10-52FFA9740042) to 0x0010. Podobną informację zwróciło polecenie 'characteristics’ (char value handle):
1 |
handle: 0x000f, char properties: 0x0a, char value handle: 0x0010, uuid: ef680101-9b35-4933-9b10-52ffa9740042 |
Do odczytania jej wartości użyjmy uchwytu do wartości, tutaj: 0x0010:
1 2 3 |
[E3:F2:CA:0B:88:1E][LE]> char-read-hnd 10 Characteristic value/descriptor: 63 6f 73 69 6b 31 [E3:F2:CA:0B:88:1E][LE]> |
Wartości szesnastkowe „63 6f 73 69 6b 31” w tablicy ASCII oznaczają „cosik1”.
Temperatura
Usługa „Environment service” ma adres 0200 (EF680200-9B35-4933-9B10-52FFA9740042). Wróćmy do wydruku 'primary’:
1 2 |
<strong>attr handle: 0x001d, end grp handle: 0x002e uuid: ef680200-9b35-4933-9b10-52ffa9740042</strong> attr handle: 0x002f, end grp handle: 0x004c uuid: ef680400-9b35-4933-9b10-52ffa9740042 |
Przeanalizujmy deskryptory od tej usługi do następnej:
1 2 3 4 5 6 7 |
[E3:F2:CA:0B:88:1E][LE]> char-desc 1d 2f handle: 0x001d, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x001e, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x001f, uuid: ef680201-9b35-4933-9b10-52ffa9740042 handle: 0x0020, uuid: 00002902-0000-1000-8000-00805f9b34fb handle: 0x0021, uuid: 00002803-0000-1000-8000-00805f9b34fb ... |
Po kolei:
Uchwyt | UUID (początek) | |
0x001d | 00002800 | 2800 oznacza uchwyt do usługi |
0x001e | 00002803 | 2803 oznacza charakterystykę |
0x001f | ef680201 | Wartość charakterystyki |
0x0020 | 00002902 | 2902 oznacza CCCD charakterystyki – wykorzystam go za chwilę |
0x0020 | 00002803 | 2803 oznacza charakterystykę |
Charakterystyka 'Temperature characteristic’ ma identyfikator 0201 – czyli EF680201-9B35-4933-9B10-52FFA9740042. Zgodnie z dokumentacją Nordica:
Temperature characteristic | 0201 | Notify | 2 bytes | Temperature in Celsius
|
Zauważcie, że charakterystyka jest typu 'notify’: po podaniu odpowiedniej instrukcji, Thingy będzie regularnie zwracał jej wartość. Zwracane są 2 bajty. Pierwszy to całkowita część temperatury – drugi to jej wartość po przecinku.
Dokumentacja Nordica mówi:
To turn on sensor reading, enable notifications from the desired characteristic by writing 0x0001 to the Client Characteristic Configuration Descriptor (CCCD) for that characteristic.
Czyli:
Żeby rozpocząć odczytywanie wartości czujnika, włącz powiadomienia zapisując wartość 0x0001 do CCCD tej charakterystyki.
Uchwyt do CCCD (Client Characteristic Configuration Descriptor) tej charakterystyki znaleźliśmy w poprzednim kroku – to 0x0020. Wywołajmy char-write-req z tym uchwytem i wartością 0100:
1 2 3 4 5 |
[E3:F2:CA:0B:88:1E][LE]> char-write-req 20 0100 Characteristic value was written successfully Notification handle = 0x001f value: 16 4d Notification handle = 0x001f value: 16 51 Notification handle = 0x001f value: 16 42 |
Thingy zaczęła zwracać wartości:)
- 16 4d, dziesiątkowo 22 i 77
- 16 51, dziesiątkowo 22 i 81
- 16 42, dziesiątkowo 22 i 66.
Wyjaśnienia wymaga podanie wartości 0100 – zamiast 0001 jak w instrukcji. Po prostu – niektóre wartości w gatttool podaje się w porządku big endian – zamiast little endian:)
Podsumowanie
No faktycznie – temat nie jest specjalnie łatwy. Ale tym razem nie chciałem iść na skróty i postanowiłem dokładnie pokazać jak się dobrać do usług BLE. Powyższe wiadomości pozwolą Wam nad nimi zapanować. A do programowania przymierzymy się w kolejnym tekście.