The brick
A Brick<T> is a connection to one NXT. Besides giving access to devices,
it has methods for the brick as a whole.
Information
nxt_rs::doc_example(|brick| async move {
let info = brick.info().await?; // name, Bluetooth address, free flash
let name = brick.name().await?; // BrickName
let battery = brick.battery().await?; // Millivolts
let fw = brick.firmware_version().await?; // FirmwareVersion { protocol, firmware }
println!("{name} [{}], {battery} ({:.1} V)", info.bluetooth_address, battery.volts());
println!("firmware {}, {} bytes of flash free", fw.firmware, info.free_flash);
Ok(()) });
Rename the brick (at most 15 ASCII characters):
nxt_rs::doc_example(|brick| async move {
brick.set_name(&"Robo".parse()?).await?;
Ok(()) });
Six fresh AA batteries read about 9 V. As the voltage drops, the motors get weaker, so check the battery when a robot behaves differently than usual.
Sound
nxt_rs::doc_example(|brick| async move {
use nxt_rs::{protocol::FileName, units::Hz};
use std::time::Duration;
brick.play_tone(Hz::C5, Duration::from_millis(150)).await?;
brick.play_tone(Hz::new(880)?, Duration::from_millis(150)).await?;
brick.files().write(&FileName::new("! Startup.rso")?, b"").await?;
brick.play_sound(&FileName::new("! Startup.rso")?, false).await?; // a sound file on the brick
brick.stop_sound().await?;
Ok(()) });
play_tone returns immediately while the brick plays the tone. To play a
melody, wait for each note’s duration between calls.
Programs
nxt_rs::doc_example(|brick| async move {
use nxt_rs::protocol::FileName;
let program = FileName::new("Demo.rxe")?;
brick.files().write(&program, b"x").await?;
brick.start_program(&program).await?;
assert_eq!(brick.current_program().await?, Some(program));
let was_running = brick.stop_program().await?; // false if nothing was running
Ok(()) });
See Files and programs for uploading programs, and Messaging for talking to them.
Staying awake
The brick switches off after its sleep timer runs out (configurable in its
Settings menu). keep_alive resets the timer and returns its length:
nxt_rs::doc_example(|brick| async move {
let timeout = brick.keep_alive().await?;
println!("the brick sleeps after {timeout:?} without keep-alive");
Ok(()) });
For long programs, spawn brick.keep_alive_task(interval) on your runtime.
It sends a keep-alive every interval until an error occurs.
Stopping everything
stop_all coasts all motors, stops sound and unconfigures all sensors. Use
it at the end of a program, or in an error handler:
nxt_rs::doc_example(|brick| async move {
brick.stop_all().await?;
Ok(()) });
Timeouts
Each request has a timeout: 1 s by default over USB, 3 s over Bluetooth and serial. To change it, construct the brick yourself:
use std::time::Duration;
use nxt_rs::{Brick, blocking::Block, transport::Usb};
fn main() -> nxt_rs::Result<()> {
let brick = Brick::with_timeout(Usb::first().block()?, Duration::from_secs(5));
Ok(()) }
A timeout returns Error::Timeout. The connection stays usable afterwards.
Clones and sharing
Brick is a cheap handle: clone it freely and send clones to other tasks or
threads. All clones share the connection, the port claims
and the timeout.