12.2. Las cuatro capas¶
La biblioteca del protocolo está construida como una pila de cuatro capas, cada una de las cuales resuelve un único problema y se apoya en la capa inferior. El resto del capítulo recorre la pila de abajo hacia arriba.
12.2.1. Transporte¶
En la parte inferior está la tubería de bytes entre la cámara y el host. A la biblioteca del protocolo no le importa cuál transporta los bytes:
USB-CDC a través del puerto USB en el que está enchufada la cámara. La opción predeterminada y de mayor ancho de banda para cada cámara.
UART a través de un par de pines GPIO de la cámara conectados a un adaptador serie en el host. Útil para implementaciones sin cabeza donde el puerto USB está ocupado o no es físicamente accesible.
El único trabajo del transporte es «los bytes entran, los bytes salen, en orden». Todo lo que está por encima de esta capa asume que el transporte entrega los bytes en el orden en que se escribieron, pero permite que los propios bytes se corrompan o que el enlace se caiga por completo. Tanto las ráfagas con pérdidas (faltan algunos bytes) como las caídas limpias (todo el enlace desaparece por un tiempo y luego regresa) se gestionan en niveles superiores.
12.2.2. Tramado¶
La siguiente capa impone estructura sobre el flujo de bytes. Cada mensaje se convierte en un paquete: una cabecera de 10 bytes seguida de una carga útil seguida de un remolque de 4 bytes. La cabecera contiene:
Una palabra de sincronización de 2 bytes (
0xD5AA) que permite a un receptor reencontrar el inicio de un paquete tras una pérdida de sincronización.Un número de secuencia de 1 byte usado por la capa de fiabilidad.
Un ID de canal de 1 byte que indica a qué flujo lógico pertenece el paquete.
Un campo de indicadores de 1 byte para los bits de ACK / NAK / fragmento / evento.
Un código de operación de 1 byte que distingue los comandos del protocolo, los comandos del sistema y los comandos de canal.
Una longitud de carga útil de 2 bytes.
Un CRC de 2 bytes sobre los ocho bytes anteriores de la cabecera.
A continuación viene la carga útil, y luego un CRC de 4 bytes sobre la propia carga útil. Los dos CRC detectan la corrupción de forma independiente: un bit invertido en la cabecera invalida el CRC de la cabecera, y el receptor puede descartar el paquete sin necesidad de leer nunca la carga útil.
12.2.3. Fiabilidad¶
La capa de fiabilidad convierte los «paquetes que podrían llegar» en «paquetes que han llegado». Rastrea los números de secuencia de la cabecera, pide al otro lado que envíe acuses de recibo por cada paquete que lo requiera y retransmite cuando un acuse de recibo no llega dentro de un tiempo de espera. De forma predeterminada, el tiempo de espera de retransmisión comienza en 500 ms y se duplica en cada reintento, con tres reintentos antes de rendirse.
Cada uno de esos comportamientos es configurable en la llamada a protocol.init(): el ACK puede desactivarse para flujos unidireccionales, la validación de CRC puede omitirse en transportes perfectamente limpios, y los parámetros de retransmisión pueden ajustarse para enlaces lentos o de alta latencia.
12.2.4. Canales¶
La capa superior es lo que ve el código de aplicación. Un canal es un flujo lógico con nombre identificado por un ID de canal de 0 a 31. Hasta 32 canales pueden coexistir en un transporte; cada uno es independiente de los demás, direccionado por su ID en la cabecera de cada paquete. La cámara arranca con cuatro canales integrados – stdin, stdout, stream y profile – y el código de aplicación registra más encima llamando a protocol.register() con una clase de Python.
Las cuatro capas no mezclan responsabilidades. El tramado no sabe nada de los canales; la fiabilidad no sabe nada del contenido de los paquetes; la capa de canal no sabe cómo llegan los bytes. Esa separación es la razón por la que un cambio de transporte (de USB a UART, por ejemplo) no se propaga hasta el código de los canales, y es lo que hace que el resto del capítulo pueda recorrerse capa por capa.