Class MavlinkConnection

Namespace
MavNet.Transport.Udp
Assembly
MavNet.Transport.Udp.dll

A MAVLink v2 UDP transport. Owns one socket, runs one receive loop, and broadcasts a GCS heartbeat at a fixed rate. Exposes inbound MAVLink as strongly-typed events keyed on the sender's MavId.

Thread model. Inbound events fire on the receive thread, synchronously. Consumers that need to marshal to a UI thread (e.g. Blazor) must do so themselves (InvokeAsync(StateHasChanged)). Subscriber exceptions are caught — a buggy subscriber cannot break the receive loop.

Sending. Use Send<T>(T) with any generated MAVLink message. The connection knows the message's MsgId, CrcExtra, and MaxPayloadLength at the call site — no runtime lookup.

Lifetime. Implements IAsyncDisposable; safe to dispose multiple times. Disposing closes the socket and stops the receive loop.

public sealed class MavlinkConnection : IMavlinkConnection, IAsyncDisposable
Inheritance
MavlinkConnection
Implements
Inherited Members

Constructors

MavlinkConnection(IPEndPoint, IPEndPoint, byte, byte, int, ILogger<MavlinkConnection>?)

Creates and binds the UDP socket. Call Start() to begin receiving.

public MavlinkConnection(IPEndPoint localBind, IPEndPoint remote, byte selfSystemId = 255, byte selfComponentId = 190, int gcsHeartbeatIntervalMs = 100, ILogger<MavlinkConnection>? logger = null)

Parameters

localBind IPEndPoint
remote IPEndPoint
selfSystemId byte
selfComponentId byte
gcsHeartbeatIntervalMs int
logger ILogger<MavlinkConnection>

Properties

LocalEndPoint

The local IPEndPoint the UDP socket is bound to. When the caller passed port 0 to the constructor, this is the OS-assigned ephemeral port.

public IPEndPoint? LocalEndPoint { get; }

Property Value

IPEndPoint

Methods

DisposeAsync()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources asynchronously.

public ValueTask DisposeAsync()

Returns

ValueTask

A task that represents the asynchronous dispose operation.

SendRaw(uint, byte, ReadOnlySpan<byte>)

Send raw bytes as a MAVLink v2 frame. Use Send<T>(T) for known message types — this is the escape hatch.

public void SendRaw(uint msgId, byte crcExtra, ReadOnlySpan<byte> payload)

Parameters

msgId uint
crcExtra byte
payload ReadOnlySpan<byte>

Send<T>(T)

Send a generated MAVLink message. Frame is built and CRC-stamped on this thread; the actual UDP send is non-blocking.

public void Send<T>(T message) where T : IMavlinkMessage<T>

Parameters

message T

Type Parameters

T

Start()

Begin reading from the socket and emitting events. Idempotent within one instance — throws if called twice.

public void Start()

Events

CommandAckReceived

Fires for every inbound COMMAND_ACK.

public event Action<MavId, CommandAck, DateTime>? CommandAckReceived

Event Type

Action<MavId, CommandAck, DateTime>

ExtendedSysStateReceived

Fires for every inbound EXTENDED_SYS_STATE.

public event Action<MavId, ExtendedSysState, DateTime>? ExtendedSysStateReceived

Event Type

Action<MavId, ExtendedSysState, DateTime>

GlobalPositionIntReceived

Fires for every inbound GLOBAL_POSITION_INT.

public event Action<MavId, GlobalPositionInt, DateTime>? GlobalPositionIntReceived

Event Type

Action<MavId, GlobalPositionInt, DateTime>

GpsRawIntReceived

Fires for every inbound GPS_RAW_INT.

public event Action<MavId, GpsRawInt, DateTime>? GpsRawIntReceived

Event Type

Action<MavId, GpsRawInt, DateTime>

HeartbeatReceived

Fires for every inbound HEARTBEAT. Args: sender, decoded message, receive timestamp.

public event Action<MavId, Heartbeat, DateTime>? HeartbeatReceived

Event Type

Action<MavId, Heartbeat, DateTime>

MissionAckReceived

Fires for every inbound MISSION_ACK.

public event Action<MavId, MissionAck, DateTime>? MissionAckReceived

Event Type

Action<MavId, MissionAck, DateTime>

MissionClearAllReceived

Fires for every inbound MISSION_CLEAR_ALL.

public event Action<MavId, MissionClearAll, DateTime>? MissionClearAllReceived

Event Type

Action<MavId, MissionClearAll, DateTime>

MissionCountReceived

Fires for every inbound MISSION_COUNT.

public event Action<MavId, MissionCount, DateTime>? MissionCountReceived

Event Type

Action<MavId, MissionCount, DateTime>

MissionCurrentReceived

Fires for every inbound MISSION_CURRENT.

public event Action<MavId, MissionCurrent, DateTime>? MissionCurrentReceived

Event Type

Action<MavId, MissionCurrent, DateTime>

MissionItemIntReceived

Fires for every inbound MISSION_ITEM_INT.

public event Action<MavId, MissionItemInt, DateTime>? MissionItemIntReceived

Event Type

Action<MavId, MissionItemInt, DateTime>

MissionItemReachedReceived

Fires for every inbound MISSION_ITEM_REACHED.

public event Action<MavId, MissionItemReached, DateTime>? MissionItemReachedReceived

Event Type

Action<MavId, MissionItemReached, DateTime>

MissionRequestIntReceived

Fires for every inbound MISSION_REQUEST_INT.

public event Action<MavId, MissionRequestInt, DateTime>? MissionRequestIntReceived

Event Type

Action<MavId, MissionRequestInt, DateTime>

MissionRequestListReceived

Fires for every inbound MISSION_REQUEST_LIST.

public event Action<MavId, MissionRequestList, DateTime>? MissionRequestListReceived

Event Type

Action<MavId, MissionRequestList, DateTime>

MissionRequestReceived

Fires for every inbound MISSION_REQUEST. Deprecated by the MAVLink spec, but ArduPilot still sends it — respond with a MISSION_ITEM_INT.

public event Action<MavId, MissionRequest, DateTime>? MissionRequestReceived

Event Type

Action<MavId, MissionRequest, DateTime>

SysStatusReceived

Fires for every inbound SYS_STATUS.

public event Action<MavId, SysStatus, DateTime>? SysStatusReceived

Event Type

Action<MavId, SysStatus, DateTime>

VfrHudReceived

Fires for every inbound VFR_HUD.

public event Action<MavId, VfrHud, DateTime>? VfrHudReceived

Event Type

Action<MavId, VfrHud, DateTime>