Architecture
MavLinkSharp is structured around three layers:
- Dialect Metadata — MAVLink XML definitions loaded at runtime into a
Metadatamodel. - Frame — the parsing/encoding engine and the MAVLink packet lifecycle.
- Connection & Protocols — high-level transport, Command/Mission/Parameter flows.
Runtime Dialect Parsing
MavLinkSharp has no code generation. At startup, MavLink.Initialize() reads standard or custom MAVLink XML dialect files and builds an in-memory model:
MavLinkContextholds the loaded state (messages, enums, commands) and drives checksums, signing, and message filtering.MetadataexposesMessages,Enums, andCommandsdictionaries for lookup.Messageholds the field definitions of one message:PayloadLength,CrcExtra, and the wire-orderedOrderedFields.Fieldresolves each XML type (uint8_t,float,char[16], ...) to a CLR type, length, and wire ordering key.
Wire ordering follows the MAVLink serialization rules — fields are sorted by native size (largest first), equal-size fields keep XML order, MAVLink 2 extension fields are appended in declaration order, and CRC_EXTRA is computed over the reordered base fields.
Frame Lifecycle
Frame is both the parse target and the encode/preview builder:
- Parse:
Frame.TryParse(ReadOnlySpan<byte>)or the streamingReadOnlySequence<byte>overload finds the start marker, decodes header/payload, verifies CRC (and, when enabled, MAVLink 2 signature), and stores the decodedMessageplus a buffer-backed payload. - Access:
Fieldslazily decodes the payload into typed values; typed accessors such asGetSingle,GetByte,GetUInt16read field spans directly. - Encode:
SetFieldswrites values into the payload at their computed offsets;ToBytesassembles the wire packet. - Lifecycle:
FrameisIDisposableand returns its buffer toArrayPool<byte>.Shared; reuse oneFrameinstance for zero-allocation parsing. - Buffer ownership:
TryParsecopies the payload into the frame's own pooled buffer, so the source buffer does not need to stay alive. Copy anything you want to retain before callingDispose()— disposal zeroes and returns the pooled arrays. Note that a frame delivered toMavLinkConnection.PacketReceivedis shared with every other handler in the same dispatch, so neither retain nor dispose it.
Connection Manager
MavLinkConnection wraps an ITransport and adds stream intelligence:
| Transport | Purpose |
|---|---|
UdpTransport |
Client- or listener-mode UDP (default MAVLink port 14550) |
TcpTransport |
TCP client/server with auto-reconnect and hostname support |
SerialTransport |
Serial ports (System.IO.Ports) |
Features: automatic packet framing via Frame, PacketReceived events, auto-heartbeat, auto-sequence numbering, reconnection, and OnCommandAck handling. ConnectionOptions controls system/component IDs, heartbeat interval, and reconnect behavior.
Protocols
High-level, asynchronous flows built on the connection layer with built-in timeout and retry:
- Command Protocol —
COMMAND_LONG/COMMAND_INTwithCOMMAND_ACKhandling and progress support. - Mission Protocol — upload, download, and clear flight plans (
MISSION_COUNT,MISSION_ITEM_INT,MISSION_ACK, ...). - Parameter Protocol — request/read/set onboard parameters with an in-memory typed
ParameterCache; extendedPARAM_EXT_*parameters add string and 64-bit values, andMAV_CMD_PARAM_TRANSACTIONprovides atomic multi-step writes.
MAVLink 2 Signing
MavLinkSigning implements MAVLink 2 packet signing (HMAC-SHA256) with random or passphrase keys and timestamp validation. Enable it per-frame (Frame.EnableSigning) or configure it at the connection level for signed links.
Streaming & Performance
ReadOnlySequence<byte>andSystem.IO.Pipelines(PipeReader) overloads handle fragmented stream input without copying.- Precompiled layout metadata gives O(1) offset lookups;
ArrayPoolandSpan<T>keep allocation near zero. - .NET 10 target uses an
XmlReader-based parser and hardware intrinsics for AOT compatibility.