11.3. Radio i warstwa łącza¶
Dwie najniższe warstwy stosu BLE są z perspektywy Pythona niemal całkowicie automatyczne – krzem radiowy oraz warstwy, które MicroPython uruchamia ponad nim, obsługują wszystko, od wyboru kanału po retransmisję utraconego pakietu. Trzy z podejmowanych przez nie decyzji nadal przebijają się do API widocznego dla użytkownika: moc, zasięg i przepustowość.
11.3.1. Radio¶
BLE używa tego samego pasma 2,4 GHz Industrial-Scientific-Medical (ISM) co Wi-Fi, kuchenki mikrofalowe i większość pozostałych technologii bezprzewodowych krótkiego zasięgu. Pasmo jest podzielone na 40 kanałów o szerokości 2 MHz.
Trzy z 40 kanałów są zarezerwowane na rozgłaszanie – krótkie transmisje, które ogłaszają obecność urządzenia każdemu, kto nasłuchuje. Są rozmieszczone w paśmie tak, by nasłuchujący mógł szybko przeszukać wszystkie trzy i by zakłócenie na którymkolwiek z nich raczej nie wyłączyło urządzenia całkowicie z eteru.
Trzydzieści siedem to kanały danych. Gdy dwa urządzenia się połączą, wymieniają na nich pakiety, przeskakując między nimi według pseudolosowej sekwencji uzgodnionej przez obie strony w momencie połączenia. Adaptacyjne przeskakiwanie częstotliwości (adaptive frequency hopping) pozwala każdej ze stron oznaczyć kanał jako zły (silne zakłócenia Wi-Fi, kuchenka mikrofalowa, sąsiednia sieć BLE), tak by sekwencja go pomijała.
40 kanałów BLE w paśmie 2,4 GHz. Trzy służą do rozgłaszania, pozostałe przenoszą ruch w otwartym połączeniu.¶
Radio transmituje krótkie pakiety – najwyżej kilka milisekund długości – a w przerwach śpi. To właśnie ten sen czyni technologię niskoenergetyczną (low energy). Typowy peripheral BLE spędza znacznie poniżej jednego procenta czasu na faktycznej transmisji; przez resztę radio jest wyłączone między zaplanowanymi zdarzeniami.
11.3.2. Warstwa łącza¶
Warstwa łącza to najmniejsza jednostka BLE, która komunikuje się ze swoim odpowiednikiem na innym urządzeniu. Realizuje cztery zadania.
Ramkowanie pakietów. Każdy pakiet niesie krótki nagłówek (adres dostępu do kanału, długość pakietu, bity sterujące), ładunek oraz CRC. Odbiornik sprawdza CRC i odrzuca wszystko, co uszkodzone.
Adresowanie. Każde urządzenie BLE ma 48-bitowy adres urządzenia, który identyfikuje je w eterze. Niektóre są publiczne – identyfikator sprzętowy przypisany przez producenta, możliwy do śledzenia na zawsze. Niektóre są losowe – generowane na urządzeniu, okresowo rotowane i opcjonalnie szyfrowane, tak by podsłuchujący nie mógł powiązać dwóch transmisji z tym samym fizycznym sprzętem. Adresy pojawiają się ponownie w Rozgłaszanie i skanowanie.
Harmonogramowanie połączenia. Gdy dwa urządzenia się połączą, warstwa łącza harmonogramuje okresowe zdarzenia radiowe w sekwencji przeskoków – co stały interwał połączenia (connection interval) – i pakuje do każdego z nich dane zakolejkowane przez warstwę GATT powyżej. Obie strony wracają do snu między zdarzeniami. Interwał połączenia to pokrętło, o które aplikacja może poprosić (zobacz Połączenia).
Niezawodność. Każdy pakiet w połączeniu jest potwierdzany przez drugą stronę. Warstwa łącza retransmituje wszystko, co nie otrzymało odpowiedzi, dzięki czemu warstwy powyżej widzą uporządkowany, bezstratny strumień bajtów. W odróżnieniu od UDP – wyślij pakiet i miej nadzieję na najlepsze po stronie sieci, BLE nie ma w normalnym użyciu osobnego trybu zawodnego – każdy pakiet w otwartym połączeniu jest ponawiany, aż dotrze albo łącze zostanie uznane za utracone.
Warstwa łącza to także miejsce, w którym działa szyfrowanie, gdy para urządzeń uzgodni klucz podczas parowania (zobacz Parowanie i wiązanie). Każdy pakiet na szyfrowanym łączu jest odszyfrowywany u odbiorcy, zanim warstwy powyżej w ogóle go zobaczą.
11.3.4. Co z tego wszystkiego widzi Python¶
Niemal nic. API bluetooth oraz aioble nie udostępniają kanałów, sekwencji przeskoków, CRC pakietów ani liczników retransmisji; wszystkim tym zajmuje się wnętrze portu BLE oraz radio. Elementy, które faktycznie się przebijają, to te udostępniane przez negocjację w momencie połączenia – interwał połączenia, MTU, typ adresu.