#lora #serial #tcp #mesh #usb-serial #tokio

meshtastic

A Rust library for communicating with and configuring Meshtastic devices

7 releases

0.1.6 Mar 20, 2024
0.1.5 Dec 22, 2023
0.1.4 Sep 7, 2023

#178 in Embedded development

Download history 91/week @ 2024-01-27 11/week @ 2024-02-03 7/week @ 2024-02-24 6/week @ 2024-03-09 115/week @ 2024-03-16 19/week @ 2024-03-23 28/week @ 2024-03-30 9/week @ 2024-04-06 41/week @ 2024-04-13

108 downloads per month

GPL-3.0 license

145KB
2K SLoC

Meshtastic.rs

Overview

Meshtastic.rs is a crate that allows you to interact with Meshtastic devices in Rust. This crate is designed to be used on a desktop environment, and currently supports connecting to radios via USB serial and TCP.

This crate is designed to be used within the tokio asynchronous runtime.

Crates.io Documentation License

Installation

You can add this crate to your project using the following command:

cargo add meshtastic

Usage

This crate provides basic TCP and serial connection examples within the /examples directory. You can run these examples using the following commands:

cargo run --example basic_tcp
cargo run --example basic_serial

TCP Example

This example requires a Meshtastic with an exposed IP port, or a simulated radio via the Meshtastic Docker instance (see here).

/// This example connects to a TCP port on the radio, and prints out all received packets.
/// This can be used with a simulated radio via the Meshtastic Docker firmware image.
/// https://meshtastic.org/docs/software/linux-native#usage-with-docker

use std::io::{self, BufRead};

use meshtastic::api::StreamApi;
use meshtastic::utils;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let stream_api = StreamApi::new();

    println!("Enter the address of a TCP port to connect to, in the form \"IP:PORT\":");

    let stdin = io::stdin();
    let entered_address = stdin
        .lock()
        .lines()
        .next()
        .expect("Failed to find next line")
        .expect("Could not read next line");

    let tcp_stream = utils::stream::build_tcp_stream(entered_address).await?;
    let (mut decoded_listener, stream_api) = stream_api.connect(tcp_stream).await;

    let config_id = utils::generate_rand_id();
    let stream_api = stream_api.configure(config_id).await?;

    // This loop can be broken with ctrl+c, or by unpowering the radio.
    while let Some(decoded) = decoded_listener.recv().await {
        println!("Received: {:?}", decoded);
    }

    // Note that in this specific example, this will only be called when
    // the radio is disconnected, as the above loop will never exit.
    // Typically you would allow the user to manually kill the loop,
    // for example with tokio::select!.
    let _stream_api = stream_api.disconnect().await?;

    Ok(())
}

Serial Example

This example requires a powered and flashed Meshtastic radio connected to the host machine via a USB serial port.

/// This example connects to a radio via serial, and prints out all received packets.
/// This example requires a powered and flashed Meshtastic radio.
/// https://meshtastic.org/docs/supported-hardware

use std::io::{self, BufRead};

use meshtastic::api::StreamApi;
use meshtastic::utils;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let stream_api = StreamApi::new();

    let available_ports = utils::stream::available_serial_ports()?;
    println!("Available ports: {:?}", available_ports);
    println!("Enter the name of a port to connect to:");

    let stdin = io::stdin();
    let entered_port = stdin
        .lock()
        .lines()
        .next()
        .expect("Failed to find next line")
        .expect("Could not read next line");

    let serial_stream = utils::stream::build_serial_stream(entered_port, None, None, None)?;
    let (mut decoded_listener, stream_api) = stream_api.connect(serial_stream).await;

    let config_id = utils::generate_rand_id();
    let stream_api = stream_api.configure(config_id).await?;

    // This loop can be broken with ctrl+c, or by disconnecting
    // the attached serial port.
    while let Some(decoded) = decoded_listener.recv().await {
        println!("Received: {:?}", decoded);
    }

    // Note that in this specific example, this will only be called when
    // the radio is disconnected, as the above loop will never exit.
    // Typically you would allow the user to manually kill the loop,
    // for example with tokio::select!.
    let _stream_api = stream_api.disconnect().await?;

    Ok(())
}

Stats

Alt

Contributing

Contributions are welcome! If you find a bug or want to propose a new feature, please open an issue or submit a pull request.

License

This project is licensed under the GPL-3.0 License.

Dependencies

~10–47MB
~679K SLoC