Skip to content

Control light#

Hardware is required. The Rust SDK is the primary control surface for host applications.

Built-in 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(3000.0), Flux::Relative(0.75))
        .await?;

    Ok(())
}

Manual per-emitter output#

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)?;
    let source = fixture
        .sources()
        .await?
        .into_iter()
        .next()
        .ok_or(enody::Error::InsufficientData)?;

    for (index, emitter) in source.emitters().await?.iter().enumerate() {
        let value = if index == 0 { 1.0 } else { 0.0 };
        emitter.set_flux(Flux::Relative(value)).await?;
    }

    fixture
        .display(Configuration::Manual, Flux::Relative(1.0))
        .await?;

    Ok(())
}

Manual mode is useful for experiments and optimization. Built-in display modes are better for ordinary application control.

Source-level display#

Fixtures and sources both expose display:

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)?;
    let source = fixture
        .sources()
        .await?
        .into_iter()
        .next()
        .ok_or(enody::Error::InsufficientData)?;

    source
        .display(Configuration::Blackbody(4000.0), Flux::Relative(0.5))
        .await?;

    Ok(())
}

Use fixture-level display when you want the whole fixture to follow the same intent. Use source-level display when a device exposes multiple independently controllable source regions.