15.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.

15.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.

15.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.

15.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.