No description
- Rust 100%
|
All checks were successful
Book / deploy (push) Successful in 1m13s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|---|---|---|
| .forgejo/workflows | ||
| contrib | ||
| docs | ||
| examples | ||
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| devenv.lock | ||
| devenv.nix | ||
| devenv.yaml | ||
| LICENSE-APACHE | ||
| LICENSE-MIT | ||
| PLAN.md | ||
| README.md | ||
| rustfmt.toml | ||
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 genericbrick.send(cmd)for any command (including your own), and raw telegrams. - High level: motors, sensors, files, mailboxes, and the display (screenshots, text and images).
- Low level: one typed method per protocol command
(
- 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.
- Devices claim their ports, so two devices can't share a socket. Taking a
group with
- 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 withmdbook serve docs. - API reference:
cargo doc --open(theguidemodule 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.