Crate mavio

source ·
Expand description

§Mavio

Minimalistic library for transport-agnostic MAVLink communication. It supports no-std (and no-alloc) targets.

🇺🇦 repository crates.io docs.rs issues

This library is a part of Mavka toolchain. It uses MAVSpec to generate MAVLink dialects.

§Usage

This library exposes Sender and Receiver to send and receive instances of MAVLink Frame. Frames contain encoded message body in Frame::payload and additional fields (such as sequence or system_id) as required by MAVLink specification. Once frame is received, it can be decoded into a specific Message. Frame decoding requires dialect specification which can be either generated manually by using MAVSpec or by enabling built-in dialect features.

Upon receiving or building a frame, it can be converted into a protocol-agnostic MavFrame, that hides generic version parameter of a Frame.

§Receive

Connect to TCP port and receive first 10 MAVLink frames, decode any received HEARTBEAT messages.

use std::net::TcpStream;
use mavio::prelude::*;
use mavio::dialects::minimal as dialect;
use dialect::Minimal;

let mut receiver = Receiver::versionless(TcpStream::connect("0.0.0.0:5600")?);

for i in 0..10 {
    let frame = receiver.recv()?;

    // Validate MAVLink frame
    if let Err(err) = frame.validate_checksum::<Minimal>() {
        eprintln!("Invalid checksum: {err:?}");
        continue;
    }

    if let Ok(Minimal::Heartbeat(msg)) = frame.decode() {
        println!(
            "HEARTBEAT #{}: mavlink_version={:#?}",
            frame.sequence(),
            msg.mavlink_version,
        );
    }
}

§Send

Connect to TCP port and send 10 HEARTBEAT messages using MAVLink 2 protocol.

use std::net::TcpStream;
use mavio::prelude::*;
use mavio::dialects::minimal as dialect;
use dialect::enums::{MavAutopilot, MavModeFlag, MavState, MavType};

// Create a TCP client sender
let mut sender = Sender::new(TcpStream::connect("0.0.0.0:5600")?);
// Create an endpoint that represents a MAVLink device speaking `MAVLink 2` protocol
let endpoint = Endpoint::v2(MavLinkId::new(15, 42));

// Create a message
let message = dialect::messages::Heartbeat {
    type_: MavType::FixedWing,
    autopilot: MavAutopilot::Generic,
    base_mode: MavModeFlag::TEST_ENABLED & MavModeFlag::CUSTOM_MODE_ENABLED,
    custom_mode: 0,
    system_status: MavState::Active,
    mavlink_version: dialect::Minimal::version().unwrap(),
};
println!("MESSAGE: {message:?}");

for i in 0..10 {
    // Build the next frame for this endpoint.
    // All required fields will be populated, including frame sequence counter.
    let frame = endpoint.next_frame(&message)?;

    sender.send(&frame)?;
    println!("FRAME #{} sent: {:#?}", i, frame);
}

§Features

This library is a building block for more sophisticated tools. It includes absolute minimum of functionality required for correct communication with everything that speaks MAVLink protocol:

  • It supports both MAVLink 1 and MAVLink 2 protocol versions.
  • Provides intermediate MAVLink packets decoding with Frame that contain only header, checksum and signature being deserialized. Which means that client don’t have to decode the entire message for routing and verification.
  • Supports optional high-level message decoding by utilizing MAVLink abstractions generated by MAVSpec.
  • Includes standard MAVLink dialects enabled by cargo features.
  • Implements message verification via checksum.
  • Provides a mechanism for message sequencing through Endpoint::next_frame, that encodes a MAVLink message into a Frame with a correct sequence as required by MAVLink protocol.
  • Includes tools for message signing.

§Extra features

Most of the “extra” features are related to decoupling from MAVLink XML definitions parsing and code generation. These tasks are performed by MAVInspect and MAVSpec respectively.

  • Supports custom dialects or may work with no dialect at all (for intermediate decoding).
  • Includes support for custom payload decoders and encoders. Which means that clients are not bounded by abstractions generated by MAVSpec.
  • Can read and write messages to anything that implements std::io::Read and std::io::Write traits.
  • Supports asynchronous I/O with AsyncSender and AsyncReceiver that available under the async feature flag.
  • Compatible with no_std targets. For such cases the library provides simplified versions of Read and Write traits.
  • Respects dialect inheritance. Messages defined in one dialect are not redefined upon inclusion into another dialect. This means that if you have a message M from dialect A being included by dialect B, it guaranteed that you can use Rust structs for message M with both of the dialects. The same is true for MAVLink enums and bitmasks.

§Out of scope

There are few stateful features required by MAVLink protocol this library intentionally does not implement and leaves for the client:

  • Sending automatic heartbeats. This is required by most of the clients which would consider nodes without heartbeat updates as inactive or invalid.
  • Stateful timestamp management for message signing ensuring, that two messages are not sent with the same timestamp.

§Dialects

Standard MAVLink dialect can be enabled by the corresponding feature flags.

  • minimal — minimal dialect required to expose your presence to other MAVLink devices.
  • standard — a superset of minimal dialect, that expected to be used by almost all flight stack.
  • common — minimum viable dialect with most of the features, a building block for other future-rich dialects.
  • ardupilotmega — feature-full dialect used by ArduPilot. In most cases this dialect is the go-to choice if you want to recognize almost all MAVLink messages used by existing flight stacks.
  • all — meta-dialect which includes all other standard dialects including these which were created for testing purposes. It is guaranteed that namespaces of the dialects in all family do not collide.
  • Other dialects from MAVLink XML definitions: asluav, avssuas, csairlink, cubepilot, development, icarous, matrixpilot, paparazzi, ualberta, uavionix. These do not include python_array_test and test dialects which should be either generated manually or as a part of all meta-dialect.

§Unsafe Features

This library does not use unsafe Rust, however, certain manipulations on MAVLink frames, if not performed carefully, could lead to data corruption and undefined behavior. All such operations are covered by unsafe cargo features and marked with in the documentation.

Most of the unsafe operations are related to updating existing frames in-place. In general, situations when you need mutable access to frames are rare. If your use-case does not strictly require such manipulations, we suggest to refrain from using functionality hidden under the unsafe feature flags.

Modules§

Structs§

Enums§

  • Version-agnostic MAVLink frame, that can be matched according to its protocol version.

Traits§

  • Interface for autogenerated or custom MAVLink dialect specification.
  • MAVLink message implementation.

Type Aliases§

  • Common result type returned by mavio functions and methods.