No description
Find a file
Kasper J. Seweryn 0b85a599e6
All checks were successful
Book / deploy (push) Successful in 1m13s
chore: release 0.2.0 with a changelog in the book
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 20:42:44 +02:00
.forgejo/workflows ci: build the book in the devenv shell 2026-10-06 09:17:18 +02:00
contrib docs: add README, user guide, protocol references and udev rule 2026-10-06 08:59:35 +02:00
docs chore: release 0.2.0 with a changelog in the book 2026-10-14 20:42:44 +02:00
examples feat(display): draw text and images on the LCD 2026-10-14 20:42:44 +02:00
src chore: release 0.2.0 with a changelog in the book 2026-10-14 20:42:44 +02:00
tests feat(display): draw text and images on the LCD 2026-10-14 20:42:44 +02:00
.gitignore docs: add mdBook user guide with a Getting Started section 2026-10-06 09:13:40 +02:00
Cargo.lock chore: release 0.2.0 with a changelog in the book 2026-10-14 20:42:44 +02:00
Cargo.toml chore: release 0.2.0 with a changelog in the book 2026-10-14 20:42:44 +02:00
devenv.lock chore: set up cargo project and dev environment 2026-10-06 08:59:35 +02:00
devenv.nix ci: build the book in the devenv shell 2026-10-06 09:17:18 +02:00
devenv.yaml chore: set up cargo project and dev environment 2026-10-06 08:59:35 +02:00
LICENSE-APACHE chore: add MIT and Apache-2.0 licenses 2026-10-06 08:59:35 +02:00
LICENSE-MIT chore: add MIT and Apache-2.0 licenses 2026-10-06 08:59:35 +02:00
PLAN.md ci: build the book in the devenv shell 2026-10-06 09:17:18 +02:00
README.md feat(display): draw text and images on the LCD 2026-10-14 20:42:44 +02:00
rustfmt.toml chore: set up cargo project and dev environment 2026-10-06 08:59:35 +02:00

nxt-rs

A type-safe, async-first Rust library for controlling LEGO MINDSTORMS NXT bricks over USB and Bluetooth, using the stock firmware's Direct and System command protocol.

use nxt_rs::prelude::*;

fn main() -> nxt_rs::Result<()> {
    let brick = Brick::usb_first().block()?;
    println!("{} — battery {}", brick.name().block()?, brick.battery().block()?);

    let (left, right, sonar) = brick.take((B.motor(), C.motor(), S4.ultrasonic())).block()?;
    let mut drive = SyncedPair::new(left, right);

    while sonar.read().block()?.is_none_or(|d| d > Centimeters(25)) {
        drive.forward(power!(60)).degrees(degrees!(90)).wait().block()?;
    }
    drive.brake().block()?;
    Ok(())
}

Features

  • Two first-class API tiers on one connection:
    • Low level: one typed method per protocol command (brick.direct().set_output_state(..), brick.system().open_read(..)), a generic brick.send(cmd) for any command (including your own), and raw telegrams.
    • High level: motors, sensors, files, mailboxes, and the display (screenshots, text and images).
  • Lots of mistakes don't compile:
    • Devices claim their ports, so two devices can't share a socket. Taking a group with brick.take((B.motor(), S1.touch())) and reusing a port in it is a compile error, as is putting a motor on a sensor input.
    • USB-only commands won't compile over Bluetooth.
    • Sensor modes are types, so readings have meaningful types.
    • power!(101) fails at compile time.
    • You can't .wait() for a motor that never stops.
  • Every command from the Bluetooth Developer Kit: 19 direct and 25 system commands.
  • Async, runtime-agnostic: works with tokio, async-std or smol. There is also .block() for plain synchronous code.
  • Transports: USB (pure Rust via nusb, no libusb), Bluetooth RFCOMM (BlueZ), serial ports (any OS), and a simulated brick for tests.
  • Self-cleaning: file and search handles close themselves, and concurrent tasks can't interleave replies.

Cargo features

Feature Default Enables
usb ✓ transport::Usb, Brick::usb_first
tracing ✓ telegram logging via tracing
bluetooth transport::Bluetooth (Linux/BlueZ; pulls in tokio)
serial transport::Serial for OS-paired Bluetooth serial ports

Documentation

  • The book: https://forge-pages.wvffle.net/wvffle/nxt-rs/, with a Getting Started guide, concepts, every API area in depth, a cookbook and reference tables. Its source is in docs/. Build it locally with mdbook serve docs.
  • API reference: cargo doc --open (the guide module has a short tour).
// Doc examples run against the built-in simulator:
use nxt_rs::{prelude::*, port::OutputPort};

let brick = Brick::mock();
let motor = brick.motor(A)?;
motor.run(power!(75)).degrees(degrees!(360)).wait().block()?;

// Drop down to the low level at any time:
let status = brick.direct().get_output_state(OutputPort::A).block()?;
assert_eq!(status.rotation_count, 360);
# Ok::<(), nxt_rs::Error>(())

License

Licensed under either of Apache License, Version 2.0 or MIT license, at your option.