Skip to main content

pamoja_mavlink/
lib.rs

1#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
2
3//! The MAVLink wire protocol for the pamoja SDK.
4//!
5//! MAVLink is the language drones speak: PX4 and ArduPilot autopilots and MAVSDK ground
6//! stations all exchange MAVLink frames, so talking to a vehicle means putting exactly the
7//! right bytes on the wire and trusting the bytes that come back. This crate is that byte
8//! layer, hand-written from the [MAVLink specification](https://mavlink.io) and pinned to
9//! its reference values rather than guessed from memory:
10//!
11//! - [`crc16_mcrf4xx`] - the CRC-16/MCRF4XX every frame carries, the checksum that lets a
12//!   receiver reject a frame mangled in transit, anchored to the catalogue check value.
13//! - [`Frame`] - the v1 and v2 frame on the wire, which both [assembles](Frame::encode_v2)
14//!   a frame to send and [parses](Frame::parse) one received, verifying the checksum and
15//!   the per-message [`message_crc_extra`] seed so a corrupt or mismatched frame never
16//!   reaches the application.
17//! - [`Parser`] - a streaming parser that turns the bytes a link delivers into whole
18//!   frames, resynchronizing on noise so a serial port or UDP socket just works.
19//! - [`signing`] - MAVLink 2 message signing: the SHA-256 signature and the monotonic
20//!   timestamp that let a ground station trust a command came from the vehicle it expects
21//!   and was not replayed.
22//! - [`dialect`] - a broad, typed slice of the common dialect (HEARTBEAT, the command,
23//!   parameter, and mission protocols, and core telemetry), plus message shapes as data:
24//!   a [`MessageDescriptor`](dialect::MessageDescriptor) gives any message's bytes named
25//!   fields, and a [builder](dialect::MessageDescriptorBuilder) describes one this crate
26//!   does not type, so a vendor or private dialect is usable at runtime.
27//! - [`protocol`] - the mission, command, and offboard exchanges as pure, allocation-free
28//!   state machines: the rules of order, matching, and retransmission that turn single
29//!   messages into a real conversation with an autopilot, with no IO of their own. Each
30//!   machine also takes a [`Frame`] at a time and hands back the frame to send, so a
31//!   caller holding a link writes no decoding or dispatch of its own.
32//!
33//! The protocol core is `no_std` and allocation-free, so the same framing runs on a
34//! microcontroller flight controller. The default `std` feature adds the async layer: the
35//! byte-stream link seam and an in-process software-in-the-loop autopilot ([`link`]), the
36//! [`vehicle`] device model that presents an autopilot as a pamoja `Device`, and the real
37//! [`drivers`] (UDP, TCP, and serial behind the `serial` feature) that carry MAVLink to a real
38//! or simulated autopilot.
39//!
40//! # Examples
41//!
42//! ```
43//! use pamoja_mavlink::dialect::{Heartbeat, Message};
44//! use pamoja_mavlink::{Frame, Header};
45//!
46//! // Announce this node as an onboard controller.
47//! let heartbeat = Heartbeat {
48//!     custom_mode: 0,
49//!     type_: 18, // MAV_TYPE_ONBOARD_CONTROLLER
50//!     autopilot: 0,
51//!     base_mode: 0,
52//!     system_status: 4, // MAV_STATE_ACTIVE
53//!     mavlink_version: 3,
54//! };
55//!
56//! // Encode it into a v2 frame, then read it back the way a peer would.
57//! let mut payload = [0u8; 255];
58//! let len = heartbeat.encode(&mut payload);
59//! let frame = Frame::encode_v2(Header::new(1, 1, 0), Heartbeat::ID, &payload[..len], Heartbeat::CRC_EXTRA)?;
60//!
61//! let received = Frame::parse(frame.as_bytes(), Heartbeat::CRC_EXTRA)?;
62//! let decoded = Heartbeat::decode(received.payload())?;
63//! assert_eq!(decoded.system_status, 4);
64//! # Ok::<(), pamoja_mavlink::MavlinkError>(())
65//! ```
66
67#[cfg(feature = "alloc")]
68extern crate alloc;
69
70mod crc;
71pub mod dialect;
72mod error;
73mod frame;
74mod parser;
75pub mod protocol;
76pub mod signing;
77
78#[cfg(feature = "std")]
79pub mod link;
80
81#[cfg(feature = "std")]
82pub mod vehicle;
83
84#[cfg(feature = "std")]
85pub mod drivers;
86
87pub use crc::{accumulate, checksum, crc16_mcrf4xx, message_crc_extra};
88pub use error::{MavlinkError, Result};
89pub use frame::{
90    Frame, Header, Version, IFLAG_SIGNED, MAGIC_V1, MAGIC_V2, MAX_FRAME, MAX_PAYLOAD, SIGNATURE_LEN,
91};
92pub use parser::Parser;
93pub use signing::{Signer, Verifier};
94
95#[cfg(feature = "std")]
96pub use vehicle::{Report, Setpoint, Vehicle};
97
98#[cfg(feature = "std")]
99pub use drivers::{TcpLink, UdpLink};
100
101#[cfg(feature = "serial")]
102pub use drivers::SerialLink;