Skip to content

Rust SDK#

The Rust crate is named enody. It provides the core message model, host-side remote runtime implementation, and CLI used by Enody developer workflows. Language bindings build around the same model for Python and JavaScript users.

Install#

[dependencies]
enody = "0.2.1"
tokio = { version = "1", features = ["full"] }

Default features include remote and cli. To use only message and trait definitions in a no_std context:

[dependencies]
enody = { version = "0.2.1", default-features = false }

Discover USB devices#

use enody::environment::Environment;
use enody::usb::UsbEnvironment;

#[tokio::main]
async fn main() -> Result<(), enody::Error> {
    let env = UsbEnvironment::new();

    for runtime in env.runtimes() {
        let host = runtime.host().await?;
        println!("Host {} v{}", host.identifier(), host.version());
    }

    Ok(())
}

Traverse resources#

use enody::environment::Environment;
use enody::usb::UsbEnvironment;

#[tokio::main]
async fn main() -> Result<(), enody::Error> {
    let env = UsbEnvironment::new();

    for runtime in env.runtimes() {
        let host = runtime.host().await?;
        for fixture in host.fixtures().await? {
            for source in fixture.sources().await? {
                let emitters = source.emitters().await?;
                println!("source {} has {} emitters", source.identifier(), emitters.len());
            }
        }
    }

    Ok(())
}

Display a blackbody target#

use enody::environment::Environment;
use enody::message::{Configuration, Flux};
use enody::usb::UsbEnvironment;

#[tokio::main]
async fn main() -> Result<(), enody::Error> {
    let env = UsbEnvironment::new();
    let runtime = env.runtimes().into_iter().next().ok_or(enody::Error::InsufficientData)?;
    let host = runtime.host().await?;
    let fixture = host.fixtures().await?.into_iter().next().ok_or(enody::Error::InsufficientData)?;

    fixture
        .display(Configuration::Blackbody(4000.0), Flux::Relative(0.8))
        .await?;

    Ok(())
}

WiFi helpers#

The public Rust WiFi module exposes:

  • WifiEnvironment for saved-token discovery.
  • WifiConnection for endpoint and discovered-device runtime creation.
  • WifiDiscoveredDevice metadata for mDNS-discovered EP01 devices.

For most applications, use the Rust CLI once to perform initial USB setup and save a token, then load that token from your host application.

Discover with saved tokens#

use enody::environment::Environment;
use enody::token_store::TokenStore;
use enody::wifi::WifiEnvironment;

#[tokio::main]
async fn main() -> Result<(), enody::Error> {
    let store = TokenStore::load()?;
    let env = WifiEnvironment::new(store.tokens().iter().cloned()).await?;

    for runtime in env.runtimes() {
        let host = runtime.host().await?;
        println!("WiFi host {} v{}", host.identifier(), host.version());
    }

    Ok(())
}

Generate and save a WiFi token#

use enody::token_store::TokenStore;
use enody::wifi::WifiConnection;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), enody::Error> {
    let devices = WifiConnection::discover_token_generation_devices(
        Duration::from_millis(800),
    )
    .await?;

    let device = devices.first().ok_or(enody::Error::InsufficientData)?;
    let token = WifiConnection::generate_token_from_discovered_device_with_approval(
        device,
        |instruction| println!("Approval required: {instruction}"),
    )
    .await?;

    let path = TokenStore::save_token(&token)?;
    println!("saved token to {}", path.display());

    Ok(())
}

Firmware updates#

The public Rust update module exposes EP01UpdateTarget for discovering attached EP01 devices, checking available firmware, updating to a selected version, and flashing a local image. Higher-level users should prefer the Rust CLI:

enody update

Rust applications that need update support can call the same public type directly.

use enody::update::EP01UpdateTarget;

#[tokio::main]
async fn main() -> Result<(), enody::Error> {
    let targets = EP01UpdateTarget::attached().await;
    let target = targets.first().ok_or(enody::Error::InsufficientData)?;

    println!("{} {}", target.info().identifier, target.info().version);

    if target.update_available().await? {
        let versions = target.available_firmware().await?;
        let selected = versions.first().ok_or(enody::Error::InsufficientData)?;
        target.update_device(selected.version()).await?;
    }

    Ok(())
}

Feature flags#

Feature Purpose
remote Host-side USB, WiFi, serial, update, and async runtime support.
cli Command-line binary support.
std Standard library support for host-side applications.

With default features disabled, message types and core traits remain available for embedded and firmware-facing use.