12.2. Cztery warstwy¶
Biblioteka protokołu jest zbudowana jako stos czterech warstw, z których każda rozwiązuje jeden problem i opiera się na warstwie poniżej. Reszta rozdziału przechodzi przez stos od dołu do góry.
12.2.1. Transport¶
Na dole znajduje się potok bajtów między kamerą a hostem. Biblioteka protokołu nie dba o to, który z nich przenosi bajty:
USB-CDC przez port USB, do którego kamera jest podłączona. Domyślna opcja o najwyższej przepustowości dla każdej kamery.
UART przez parę pinów GPIO kamery połączonych z adapterem szeregowym po stronie hosta. Przydatne w wdrożeniach bezgłowych, gdzie port USB jest zajęty lub nie jest fizycznie dostępny.
Jedynym zadaniem transportu jest „bajty wchodzą, bajty wychodzą, w kolejności”. Wszystko powyżej tej warstwy zakłada, że transport dostarcza bajty w kolejności, w jakiej zostały zapisane, ale dopuszcza, że same bajty mogą zostać uszkodzone lub że łącze może całkowicie zerwać. Stratne serie (kilka brakujących bajtów) i czyste zerwania (całe łącze nieobecne przez chwilę, a potem z powrotem) są obsługiwane wyżej.
12.2.2. Ramkowanie¶
Następna warstwa narzuca strukturę na strumień bajtów. Każda wiadomość staje się pakietem – 10-bajtowy nagłówek, po którym następuje ładunek, a po nim 4-bajtowy zwiastun. Nagłówek niesie:
2-bajtowe słowo synchronizacji (
0xD5AA), które pozwala odbiorcy ponownie odnaleźć początek pakietu po utracie synchronizacji.1-bajtowy numer sekwencyjny używany przez warstwę niezawodności.
1-bajtowy identyfikator kanału, który mówi, do którego logicznego strumienia należy pakiet.
1-bajtowe pole flag dla bitów ACK / NAK / fragment / event.
1-bajtowy kod operacji, który odróżnia polecenia protokołu, polecenia systemowe i polecenia kanału.
2-bajtową długość ładunku.
2-bajtowy CRC obliczony z poprzednich ośmiu bajtów nagłówka.
Następnie następuje ładunek, a po nim 4-bajtowy CRC obliczony z samego ładunku. Te dwa CRC niezależnie wychwytują uszkodzenia: odwrócony bit w nagłówku unieważnia CRC nagłówka, a odbiorca może odrzucić pakiet bez konieczności odczytywania ładunku.
12.2.3. Niezawodność¶
Warstwa niezawodności zamienia „pakiety, które mogą dotrzeć” w „pakiety, które dotarły„. Śledzi numery sekwencyjne w nagłówku, prosi drugą stronę o wysyłanie potwierdzeń dla każdego pakietu, który tego wymaga, i retransmituje, gdy potwierdzenie nie dociera w czasie wyznaczonym przez limit czasu. Domyślnie limit czasu retransmisji zaczyna się od 500 ms i podwaja się przy każdej ponownej próbie, z trzema ponownymi próbami przed poddaniem się.
Każde z tych zachowań można skonfigurować w wywołaniu protocol.init(): ACK można wyłączyć dla jednokierunkowych strumieni, walidację CRC można pominąć na całkowicie czystych transportach, a parametry retransmisji można dostroić do wolnych łączy lub łączy o dużym opóźnieniu.
12.2.4. Kanały¶
Najwyższa warstwa to to, co widzi kod aplikacji. Kanał to nazwany logiczny strumień identyfikowany przez identyfikator kanału od 0 do 31. Do 32 kanałów może współistnieć na jednym transporcie; każdy z nich jest niezależny od pozostałych, adresowany swoim identyfikatorem w nagłówku każdego pakietu. Kamera uruchamia się z czterema wbudowanymi kanałami – stdin, stdout, stream i profile – a kod aplikacji rejestruje kolejne na wierzchu, wywołując protocol.register() z klasą Pythona.
Cztery warstwy nie mieszają zagadnień. Ramkowanie nie wie nic o kanałach; niezawodność nie wie nic o zawartości pakietów; warstwa kanałów nie wie, jak bajty docierają. To rozdzielenie sprawia, że zamiana transportu (na przykład z USB na UART) nie rozchodzi się w górę do kodu kanałów, i to właśnie pozwala przejść przez resztę rozdziału po jednej warstwie naraz.