Thingy 52: usługi pod Raspberry Pi Zero (W)

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:

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:

‚-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.

Teraz wywołajcie polecenie „connect„:

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„:

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ę:

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:

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:

Sprawdźmy deskryptory usługi – zaczynając od uchwytu 0x000e aż do następnej usługi – 0x0001d:

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):

Do odczytania jej wartości użyjmy uchwytu do wartości, tutaj: 0x0010:

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’:

Przeanalizujmy deskryptory od tej usługi do następnej:

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

  • int8_t – integer
  • uint8_t – decimal

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:

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.

Źródła

Dodaj komentarz