rstango 0.4.0

Implementation of the Tango distributed control system
Documentation
//! Subscribing to the events of a device, against a device of the `server` example:
//! the change events its position pushes when it moves, and the events of the configuration
//! of the position changing.
//!
//! ```sh
//! cargo run --example events -- test/motor/1
//! ```

use std::time::Duration;
use std::{env, thread};

use tango::dev::{AttrValueEvent, DevProxy};
use tango::error::{ErrorKind, Result};


fn main() -> Result<()> {

    let name = env::args().nth(1).unwrap_or_else(|| "test/motor/1".to_string());
    let motor = DevProxy::new(name.as_str());

    // Nothing is subscribed until the channel is polled, which is ensured here so that no
    // move made below can be missed. Dropping the channel unsubscribes.
    let mut position = motor.subscribe_attr_value::<f64>("position", AttrValueEvent::Change);
    position.ensure_subscribed()?;

    // There is no initial event, the current value is read once subscribed.
    println!("Subscribed, position is {:?}", motor.read_attr::<f64, _>("position")?.value);

    // Something else moves the axis meanwhile, here another thread of this process. The
    // proxy is shared by cloning it, which shares its connection too.
    let mover = motor.clone();
    let moves = thread::spawn(move || -> Result<()> {
        for target in [10.0, 20.0, 30.0, 0.0] {
            thread::sleep(Duration::from_millis(300));
            mover.command::<_, f64>("MoveTo", target)?;
        }
        Ok(())
    });

    // A channel gives the latest event: a subscriber that does not keep up skips to it.
    loop {
        match position.wait(Duration::from_secs(1)) {
            Ok(read) => println!("position changed to {:?}, at {:?}", read.value, read.time),
            Err(err) if err.kind() == ErrorKind::TimedOut => break,
            Err(err) => println!("event failed: {err}"),
        }
    }

    moves.join().unwrap()?;

    // The configuration of an attribute has events of its own, which carry the whole of it.
    let mut conf = motor.subscribe_attr_config("position");
    conf.ensure_subscribed()?;

    let mut info = motor.attr_info("position")?;
    let format = info.config.display_format.clone();
    info.config.display_format = Some("%8.4f".into());
    motor.set_attr_config(&[("position", info.config.clone())])?;
    println!("display format changed to {:?}", conf.wait(Duration::from_secs(1))?.config.display_format);

    // Put back as it was.
    info.config.display_format = format;
    motor.set_attr_config(&[("position", info.config)])?;
    println!("display format put back to {:?}", conf.wait(Duration::from_secs(1))?.config.display_format);

    Ok(())

}