12.2. Чотири рівні¶
Бібліотека протоколу побудована як стек із чотирьох рівнів, кожен з яких вирішує одну задачу та спирається на рівень нижче. Решта розділу проходить стек знизу вгору.
12.2.1. Транспорт¶
Знизу знаходиться байтовий канал між камерою та хостом. Бібліотеці протоколу байдуже, який саме використовується:
USB-CDC через USB-порт, до якого підключено камеру. Типовий і найбільш широкосмуговий варіант для кожної камери.
UART через пару виводів GPIO на камері, підключених до серійного адаптера на хості. Корисний для автономних розгортань, де USB-порт зайнятий або фізично недоступний.
Єдине завдання транспорту – «байти надходять, байти виходять, у порядку надходження». Все, що знаходиться вище цього рівня, припускає, що транспорт доставляє байти в тому порядку, в якому вони були записані, але допускає, що самі байти можуть бути пошкоджені або зв’язок може зникнути повністю. Переривчасті втрати (кілька відсутніх байтів) та чисті відключення (весь зв’язок зник на деякий час, потім відновився) обробляються вищими рівнями.
12.2.2. Кадрування¶
Наступний рівень вгору накладає структуру на потік байтів. Кожне повідомлення стає пакетом – 10-байтовий заголовок, за яким іде корисне навантаження, а потім 4-байтовий трейлер. Заголовок містить:
2-байтове синхрослово (
0xD5AA), що дозволяє приймачу знову знайти початок пакету після десинхронізації.1-байтовий порядковий номер, що використовується рівнем надійності.
1-байтовий ідентифікатор каналу, що вказує, до якого логічного потоку належить пакет.
1-байтове поле прапорів для бітів ACK / NAK / фрагмент / подія.
1-байтовий код операції, що розрізняє команди протоколу, системні команди та команди каналів.
2-байтова довжина корисного навантаження.
2-байтовий CRC над попередніми вісьмома байтами заголовку.
Далі йде корисне навантаження, потім 4-байтовий CRC над самим корисним навантаженням. Два CRC незалежно виявляють пошкодження: перевернутий біт у заголовку анулює CRC заголовку, і приймач може відкинути пакет, не читаючи корисне навантаження.
12.2.3. Надійність¶
Рівень надійності перетворює «пакети, які можуть прибути» на «пакети, які прибули.» Він відстежує порядкові номери в заголовку, просить іншу сторону надсилати підтвердження для кожного пакету, що цього потребує, і повторно передає, якщо підтвердження не надходить протягом таймауту. За замовчуванням таймаут повторної передачі починається з 500 мс і подвоюється при кожній наступній спробі, з трьома спробами перед здачею.
Кожна з цих поведінок налаштовується у виклику protocol.init(): ACK можна вимкнути для однонаправлених потоків, перевірку CRC можна пропустити на повністю надійних транспортах, а параметри повторних передач можна налаштувати для повільних або каналів з великою затримкою.
12.2.4. Канали¶
Верхній рівень – це те, що бачить код застосунку. Канал – це іменований логічний потік, ідентифікований ідентифікатором каналу від 0 до 31. До 32 каналів можуть одночасно існувати на одному транспорті; кожен є незалежним від інших, адресується за своїм ідентифікатором у заголовку кожного пакету. Камера завантажується з чотирма вбудованими каналами – stdin, stdout, stream і profile – і код застосунку реєструє більше поверх них, викликаючи protocol.register() з класом Python.
Чотири рівні не змішують завдання. Кадрування не знає про канали; надійність не знає про вміст пакетів; рівень каналів не знає, як надходять байти. Ця розділеність – ось чому заміна транспорту (наприклад, USB на UART) не поширюється на код каналів, і саме тому решту розділу можна розглядати по одному рівню за раз.