12.10. Wrap up#

A cam plugged into a USB cable that streams frames to a host program, accepts config updates back from the host, and survives unplug/replug without losing sync – with retransmits hidden, multiple logical streams sharing one port, and zero framing code in the application – comes out of about forty lines of cam-side code and a similar amount on the host. The protocol library turns a byte pipe into a programmable channel surface and keeps everything below the application invisible.

12.10.1. What the chapter built#

  • A four-layer mental model of the stack: transport, framing, reliability, channels. Each layer solves one problem and ignores everything above.

  • The on-the-wire packet format – 10-byte header with CRC, variable payload, trailing CRC. Small enough to walk through byte by byte.

  • The handshake the cam and host run when a transport connects: PROTO_SYNC, capability exchange, channel discovery.

  • The reliability machinery on top: sequence numbers, ACKs, NAKs, retransmits with exponential backoff, the ten status codes.

  • The channel model: up to 32 named logical streams on one wire, with built-in stdin / stdout / stream / profile and application channels registered by Python class.

  • The backend interface – size, read, write, poll, lock / unlock, shape, ioctl, flush, is_active – and how the protocol library uses the methods present on a backend to decide what the channel supports.

  • The host side: the openmv-python SDK’s Camera class, the 921600-baud magic rate that switches USB-CDC into protocol mode, and the channel_size / channel_read / channel_write round-trip pattern.

  • A frame-streaming pattern – single-buffer capture, readp with a latch, send_event for new-frame notifications – and a bidirectional config pattern (host-writable channel, JSON round-trip) that together form the foundation for every interactive cam tool.

12.10.2. Reference roadmap#

The library reference pages are the lookup destinations when one of these features comes up in real code:

  • protocol — OpenMV Protocol Channels – the protocol module, protocol.init(), protocol.register(), ProtocolChannel, channel flag constants, and the per-cam max-payload table.

  • The host SDK – pip install openmv, openmv.camera.Camera. Methods touched in this chapter: update_channels(), has_channel(), channel_size(), channel_read(), channel_write(), poll_events(), read_frame(), exec(), and stop().

  • The openmv-projects repository – real tools built on the protocol library. The tools/ directory includes thermal-overlay-calibration (RGB + thermal alignment GUI), ccm-tuning (colour-correction matrix tuner), genx320-event-streaming and genx320-overlay-calibration (event-camera tooling). Each one uses the patterns from this chapter end to end.

12.10.3. Where to take it next#

A few directions cam projects move from here:

  • Building a host GUI. A frame channel feeding a video widget, one or two config channels feeding sliders and buttons. For the GUI layer itself, DearPyGui is the natural choice – pure-Python, pip-installable, fast enough for live preview, and what every existing OpenMV host tool reaches for first.

  • Multi-channel telemetry dashboard. Several application channels on the same cam (sensor readings, counters, status events) each refreshed in its own callback, and a host GUI that reads them on a timer and renders each one separately. The channel layer’s independent flow control means one slow read doesn’t stall the others.

  • Remote tuning over UART. The same channel callbacks; the application calls protocol.init to switch from USB to a UART transport. The cam keeps running headless and a Python script on a Raspberry Pi or laptop talks to it over a serial line for field tuning.

The wire format, the reliability layer, and the channel abstraction don’t change. Picking the transport that fits the deployment and adding a channel for each thing the host needs to see or set is the entire engineering job from here on.