DroneProtocol, hides the difference so the rest of the app does not care which firmware is on the other end.
MAVLink v2 framing
MAVLink v2 is a binary protocol. Every frame has the same layout:- STX is
0xFDfor v2. - LEN is the payload length. v2 trims trailing zero bytes from the payload, so the receiver restores the full length before decoding.
- MSGID is 3 bytes.
- CRC is CRC-16/MCRF4XX over the frame, seeded with a per-message CRC_EXTRA byte.
- SIGNATURE is present when bit 0 of
INC_FLAGSis set: link id, a 48-bit timestamp and a 6-byte signature.src/lib/protocol/mavlink-signer.tsbuilds and checks it.
CRC_EXTRA
Every MAVLink message definition has a CRC_EXTRA constant derived from its field layout. If the sender and the receiver disagree on a message’s layout, the CRC fails and the frame is dropped. Mission Control keeps the CRC_EXTRA value and the full payload length for every message it decodes insrc/lib/protocol/mavlink-crc-extra.ts (CRC_EXTRA and PAYLOAD_LENGTHS).
Parser
src/lib/protocol/mavlink-parser.ts is a streaming parser. It accumulates bytes from the transport in whatever chunks they arrive, scans for 0xFD, reads the header and payload, restores zero-trimmed payloads, checks the CRC and emits a typed MAVLinkFrame.
The DroneProtocol interface
DroneProtocol is defined in src/lib/protocol/types/protocol.ts. Every adapter implements it: MAVLinkAdapter, MSPAdapter, and the demo-mode MockProtocol. Its methods fall into groups:
?) that only some firmwares implement, such as iNav safehomes and geozones or fence and rally upload.
ProtocolCapabilities (in src/lib/protocol/types/core.ts) is a set of booleans such as supportsParameters, supportsMissionUpload, supportsCalibration, supportsFailsafe, supportsOsd and supportsFirmwareFlash. The UI reads it before showing a feature. A flight controller configuration panel that depends on one names it as its requiredCapability, so the panel does not appear for a firmware that lacks it.
MAVLink adapter
MAVLinkAdapter (src/lib/protocol/mavlink-adapter.ts) implements DroneProtocol for ArduPilot and PX4. Its work is split across sibling files:
ArduPilot and PX4 share MAVLink but differ in parameter names, mode numbers and some command meanings. The adapter learns the firmware from the heartbeat and from
AUTOPILOT_VERSION, then applies the matching mode map and parameter metadata.
MSP adapter
MSPAdapter (src/lib/protocol/msp-adapter.ts) implements DroneProtocol for Betaflight and iNav. MSP is a different kind of protocol:
- Request and response, with one request outstanding at a time.
msp/msp-serial-queue.tsserializes requests and matches each reply. - MSPv1 framing with an XOR checksum, and MSPv2 framing with a CRC-8 DVB-S2 checksum. The parser in
msp/msp-parser.tsalso handles jumbo frames. - No named parameters. Configuration lives in binary blocks (PID profile, rate profile, OSD layout, serial ports and so on).
msp-adapter-telemetry.ts (polled telemetry), msp-adapter-commands.ts (commands) and msp-adapter-params.ts (virtual parameters).
Virtual parameters
Because Betaflight and iNav have no parameter store, the MSP adapter maps fields of the configuration blocks to virtual parameter names such asBF_RC_RATE, BF_RC_EXPO and BF_ROLL_RATE. The definitions live in src/lib/protocol/msp/virtual-params/. This lets the usePanelParams hook, which every configuration panel uses, read and write Betaflight settings the same way it handles MAVLink parameters.
Encoders
MAVLink encoding lives insrc/lib/protocol/encoders/. index.ts re-exports every module, and src/lib/protocol/mavlink-encoder.ts re-exports the barrel.
Transports
The adapters do not care how bytes arrive. Each transport implements theTransport interface in src/lib/protocol/types/transport.ts; the implementations are in src/lib/protocol/transport/.
Demo mode does not use a transport to a real device.
MockProtocol implements DroneProtocol directly and feeds the same stores a real connection would. The demo fleet is described on Dashboard.
The agent-side router
On a node, MAVLink does not go from the flight controller to the browser directly. The agent’s native router (ados-mavlink-router, run by the ados-mavlink unit) owns the flight controller’s serial link, fans frames out on /run/ados/mavlink.sock for other agent services, and serves the stream to Mission Control over the WebSocket on :8765. A client needs a short-lived HMAC ticket before the router bridges it to the flight controller. See MAVLink proxy.
Message flow example
Next steps
State management
How decoded telemetry reaches the stores and the UI.
Code recipes
Add a MAVLink decoder or a configuration panel step by step.