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 focuses on I/O and uses MAVSpec to generate MAVLink dialects.

Β§Features

Mavio is focused on I/O primitives for MAVLink that can be used in no-std and no-alloc environments. Since Mavio is designed as a building block for more sophisticated tools, it includes absolute minimum of functionality required for correct communication with everything that speaks MAVLink protocol.

Β§Basic capabilities

  • Mavio 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.

Β§Flexible approach to I/O

Mavio is designed to be flexible and useful in different scenarios.

  • It can work without any MAVLink dialect at all (for intermediate decoding and proxying).
  • Includes support for custom payload decoders and encoders. Which means that clients are not bounded by abstractions generated by MAVSpec.
  • Uses implementation-agnostic I/O primitives with a variety of I/O adapters.
  • Provides synchronous I/O adapters for embedded-io and std::io.
  • Supports asynchronous I/O by providing lightweight adapters for embedded-io-async, Tokio, and futures-rs.

Such features are mainly related to the functionality provided by other parts of Mavka toolchain. These tasks are mainly performed by MAVInspect and MAVSpec (a message definition parser and code-generator respectively). In particular:

  • Mavio allows to use custom MAVLink dialects. This includes both dialects generated from XML definitions and ad-hoc dialects defined with pure Rust.
  • 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.
  • Provides optional support for MAVLink microservices as sub-dialects and helpers to work with them such as mission file format.

Β§Serialization / deserialization and FFI

Mavio provides support for serde and specta. The latter is supported only for std targets. All MAVLink entities are fully supported.

Β§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 heartbeats as inactive or invalid.
  • Stateful timestamp management for message signing (ensuring, that two messages are not sent with the same timestamp).
  • Retry logic for failed connections.

All such features are provided by Maviola.

Β§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;

// Create a TCP client receiver
let reader = StdIoReader::new(TcpStream::connect("0.0.0.0:5600")?);
let mut receiver = Receiver::versionless(reader);

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 writer = StdIoWriter::new(TcpStream::connect("0.0.0.0:5600")?);
let mut sender = Sender::new(writer);

// 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);
}

Β§I/O

We provide lightweight Read / Write and AsyncRead / AsyncWrite pairs for synchronous and asynchronous I/O.

Mavio packages a set of I/O adapters available under the corresponding feature flags:

See adapters for details.

Β§Dialects

Standard MAVLink dialect can be enabled by the corresponding feature flags (dlct-<dialect name>).

  • 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 those 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.

For example:

use mavio::dialects::common as dialect;
use dialect::{Common, messages::Heartbeat};
use mavio::prelude::*;

let frame: Frame<V2> = /* obtain a frame */

// Decode MavLink frame into a dialect message:
match frame.decode()? {
    Common::Heartbeat(msg) => {
        /* process heartbeat */
    }
    /* process other messages */
};

Β§Default Dialect

When standard MAVLink dialects are used and at least minimal Cargo feature is enabled, this library exposes default_dialect and DefaultDialect entities that allow to access the most feature-rich enabled MAVLink dialect.

Β§Microservices

Mavio re-exports MAVLink microservices from MAVSpec. To control which microservices you want to generate, use msrv-* feature flags family. Check MAVSpec API docs for details.

At the moment, microservices are generated only for default_dialect and can be accessed through default_dialect::microservices.

In addition, Mavio re-exports extra tools for working with microservices. These tools can be enabled by msrv-utils-* feature flags and available in microservices module.

`msrv-utils-*` are considered unstable for now! Use `unstable` feature flag to enable them.

Microservice utils feature flags:

Β§Message definitions

It is possible to bundle message definitions generated by MAVInspect into definitions module. This can be useful for ground control stations that require to present the user with the descriptions of MAVLink entities.

To enable definitions bundling use definitions feature flag.

Message definitions available only with `std` feature enabled. Otherwise, this will cause build to fail.

Β§Caveats

The API is straightforward and generally stable, however, some caution is required when working with edge-cases.

Β§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.

Β§Unstable Features

Certain features are considered unstable and available only when unstable feature flag is enabled. Unstable features are marked with ⍚ and are may be changed in futures versions.

Β§Incompatible Features

  • Specta requires std feature to be enabled.
  • MAVlink definitions requires std feature to be enabled.

Β§Binary Size

For small applications that use only a small subset of messages, avoid using dialect enums as they contain all message variants. Instead, decode messages directly from frames:

use mavio::dialects::common as dialect;
use dialect::messages::Heartbeat;
use mavio::prelude::*;

let frame: Frame<V2> = /* obtain a frame */

// Use only specific messages:
match frame.message_id() {
    Heartbeat::ID => {
        let msg = Heartbeat::try_from(frame.payload())?;
        /* process heartbeat */
    }
    /* process other messages */
};

This will help compiler to throw away unnecessary pieces of code.

Additionally, you may use default_dialect::microservices as well as microservices tools to reduce the API surface you are interacting with.

Β§Feature flags

In most of the cases you will be interested in dlct-* features, I/O providers, and alloc / std target specification. However, a more fine-grained control may be required.

Β§Generic features

  • default β€” Default features (nothing is enabled).
  • unstable β€” Enable unstable API features.
  • extras β€” Additional auxilary tools.
  • unsafe β€” Unsafe features, that allow access to internal state of the entities.
  • alloc β€” Enable memory allocation support.
  • std β€” Enable Rust std library.
  • sha2 β€” Enable sha2 backend for message signing

Β§Serialization and reflection

These features enable serde and specta support.

  • serde β€” Enable serde support.
  • specta β€” Enable specta support.

Β§I/O providers

These features enable I/O providers such as Tokio or embedded-io

  • futures β€” Enable async support via futures-rs
  • tokio β€” Enable async support via Tokio
  • embedded-io β€” Enable synchronous I/O support from embedded HAL
  • embedded-io-async β€” Enable asynchronous I/O support from embedded HAL

Β§MAVSpec tools

These features package additional MAVSpec utils suc as derive macros and message definitions.

  • derive β€” Adds derive macros for MAVLink entities.

    You can access them as mavio::derive.

  • definitions β€” Bundles MAVLink message definitions.

    Message definitions will be generated only for bundled MAVLink dialects. Microservices will be ignored as they are just subsets of existing dialects.

    Note, that while being useful for ground control stations, the generated definitions is quite large and may bloat the size of the binary.

    ⚠️ This feature won’t compile without std feature enabled.

Β§Dialects

Bundle standard MAVLink dialects as defined in XML message definitions generated by MAVSpec.

  • dlct-ardupilotmega β€” Include ardupilotmega dialect
  • dlct-asluav β€” Include ASLUAV dialect
  • dlct-avssuas β€” Include AVSSUAS dialect
  • dlct-common β€” Include common dialect
  • dlct-cs_air_link β€” Include csAirLink dialect
  • dlct-cubepilot β€” Include cubepilot dialect
  • dlct-development β€” Include development dialect
  • dlct-icarous β€” Include icarous dialect
  • dlct-matrixpilot β€” Include matrixpilot dialect
  • dlct-minimal β€” Include minimal dialect
  • dlct-paparazzi β€” Include paparazzi dialect
  • dlct-standard β€” Include standard dialect
  • dlct-ualberta β€” Include ualberta dialect
  • dlct-uavionix β€” Include uAvionix dialect
  • dlct-all β€” Include all meta-dialect

These features will control generation of MAVLink microservice-specific bindings.

  • msrv-all β€” Support for all MavLink microservices
  • msrv-heartbeat β€” Heartbeat protocol support
  • msrv-mission β€” Mission protocol support
  • msrv-parameter β€” Parameter protocol support
  • msrv-parameter-ext β€” Extended parameter protocol support
  • msrv-command β€” Command protocol support
  • msrv-manual-control β€” Manual control protocol support
  • msrv-camera β€” Camera protocol v2 support
  • msrv-gimbal-v1 β€” Gimbal protocol v1 support
  • msrv-gimbal-v2 β€” Gimbal protocol v2 support
  • msrv-arm-auth β€” Arm authorization protocol support
  • msrv-image-transmission β€” Image transmission protocol support
  • msrv-ftp β€” File transfer protocol support
  • msrv-landing-target β€” Landing target protocol support
  • msrv-ping β€” Ping protocol support
  • msrv-path-planning β€” Path planning protocol support
  • msrv-battery β€” Battery protocol support
  • msrv-terrain β€” Terrain protocol support
  • msrv-tunnel β€” Tunnel protocol support
  • msrv-open-drone-id β€” Open Drone ID protocol support
  • msrv-high-latency β€” High latency protocol support
  • msrv-component-metadata β€” Component metadata protocol support
  • msrv-payload β€” Payload protocol support
  • msrv-traffic-management β€” Traffic management protocol support
  • msrv-events-interface β€” Events interface protocol support
  • msrv-time-sync β€” Time synchronization protocol support

These features will enable additional MAVLink utilities such as *.waypoints files support, mission planninc, etc.

⚠️ All such features require unstable feature to be enabled in order to take effect.

  • msrv-utils-all β€” All MAVLink microservices utils

    ⚠️ Requires unstable feature to take effect.

  • msrv-utils-mission β€” Mission protocol utils

    ⚠️ Requires unstable feature to take effect.

Β§Technical features

These features should not be used directly.

  • msrv β€” βŠ› Enable MAVLink microservices support

    Do not use directly as this feature does not give access to any specific functionality by itself. Instead, use one of msrv-* features.

  • msrv-utils β€” βŠ›οΈ Enables MAVLink microservices extra utils

    Do not use directly as this feature does not give access to any specific functionality by itself. Instead, use one of msrv-utils-* features.

ModulesΒ§

consts
Constants
default_dialect
mavspec Default MAVLink dialect module
definitions
mavspec MAVLink message definitions
derive
mavspec MAVSpec procedural macros
dialects
mavspec MAVLink dialects
error
Errors
io
Basic MAVLink I/O
mavspec
mavspec MAVSpec re-exported
microservices
mavspec Tools for MAVLink microservices
prelude
Common imports
protocol
MAVLink protocol
utils
Utils

StructsΒ§

AsyncReceiver
Receives MAVLink frames asynchronously.
AsyncSender
Sends MAVLink frames asynchronously.
Endpoint
MAVLink device with defined ID and internal frame sequence counter.
Frame
MAVLink frame.
MavLinkId
mavspec MAVLink device ID.
Receiver
Receives MAVLink frames.
Sender
Sends MAVLink frames.

EnumsΒ§

DefaultDialect
mavspec Default MAVLink dialect
Error
mavio top-level error.
MavFrame
Version-agnostic MAVLink frame, that can be matched according to its protocol version.

TraitsΒ§

Dialect
mavspec Interface for autogenerated or custom MAVLink dialect specification.
Message
mavspec MAVLink message implementation.

Type AliasesΒ§

Result
Common result type returned by mavio functions and methods.