12.1. Зачем нужна библиотека протокола

Пары проводов и скорости передачи (бод) достаточно, чтобы перемещать байты от камеры к ПК-хосту. И USB-CDC, и UART дают программе камеры поток, где write помещает байты в один конец, а read забирает их с другого. Так что же добавляет поверх этого библиотека протокола?

Три вещи, которые вам пришлось бы писать самостоятельно каждый раз, если бы вы пытались построить серьёзный канал «камера-хост» напрямую на сырых байтах:

Формирование кадров (framing). У потока байтов нет внутренней структуры. Камера записывает temp=42, а хост читает temp= и затем прерывание, прибывающее позже, после чего 42 и следующее сообщение, начинающееся с humid=..., уже наслаивается на него. У байтов нет границ. Каждый нетривиальный канал связи с хостом в итоге изобретает некий маркер – \n между сообщениями, заголовки с префиксом длины, escape-последовательности для бинарных полезных данных – чтобы получатель знал, где одно сообщение заканчивается, а следующее начинается. Библиотека протокола даёт вам единообразный формат пакета с синхрословом и полем длины, и получателю никогда не приходится гадать.

Надёжность. USB-CDC в нормальном режиме не теряет байты молча, но UART теряет (когда хост недостаточно быстро обслуживает порт), а отсоединённый и заново подключённый последовательный кабель может оставить одну из сторон с частичным пакетом. Правильный подход – обнаружить повреждение, попросить другую сторону повторить передачу и передавать в прикладной код только сообщения, прибывшие целыми. Библиотека протокола делает это для каждого пакета с помощью CRC и поквартирных подтверждений (per-packet acknowledgements) – включённых по умолчанию; приложение не видит повторных передач.

Мультиплексирование. Между камерой и хостом есть ровно один порт USB-CDC. Если камера передаёт изображение и хост отправляет ей конфигурацию и OpenMV IDE читает stdout для вывода print, всем трём обменам приходится делить этот единственный поток байтов. Библиотека протокола присваивает каждому независимому потоку номер канала, позволяет камере зарегистрировать для каждого из них класс Python и не даёт операциям чтения хоста на одном канале мешать другим. С точки зрения прикладного кода каждый канал выглядит как его собственная отдельная линия связи.

12.1.1. Почему бы не написать это самому

Вы можете. Это несколько недель работы, чтобы заставить все три части корректно работать на последовательной линии, и ещё несколько недель, чтобы формирование кадров чисто справлялось с восстановлением после «горячего» подключения, повторные передачи работали без расходования энергии на циклы обмена, а мультиплексор переживал частичные чтения, не превращая байты одного канала в байты другого.

Библиотека протокола уже проделала эту работу, прошла проверку на каждой поддерживаемой камере и имеет соответствующие библиотеки на стороне хоста, которые говорят на том же протокольном формате. Её использование означает, что код на стороне камеры – это один небольшой класс на канал, а код на стороне хоста – объект Camera с методами channel_read и channel_write. Сэкономленное умственное пространство уходит на то, что приложение действительно делает.

Эта глава обучает протоколу с самых основ: протокольный формат, правила формирования кадров, механизм надёжности, модель каналов и, наконец, классы Python на обоих концах. К концу читатель сможет построить хост-GUI, который общается с камерой, скрипт, передающий данные датчика с камеры на ноутбук, и тот тип интерактивного инструмента калибровки, что поставляется в openmv-projects/tools/.