Skip to main content

add_function_block/
add_function_block.rs

1// Adds a statistics function block, connects a reference channel's signal to
2// its input port, and reads back the averaged output signals.
3
4use opendaq::{Channel, Instance, InstanceBuilder, MultiReader, Signal};
5
6/// The signal with the given local id.  Match on local id, not name: a
7/// signal's name is a mutable display label, while its local id is the stable
8/// identifier within its parent.
9fn signal_by_local_id(signals: &[Signal], local_id: &str) -> opendaq::Result<Option<Signal>> {
10    for signal in signals {
11        if signal.local_id()? == local_id {
12            return Ok(Some(signal.clone()));
13        }
14    }
15    Ok(None)
16}
17
18fn main() -> opendaq::Result<()> {
19    // Instance::new() already loads the bundled modules; build from an
20    // InstanceBuilder when you want to control the module search path.
21    let builder = InstanceBuilder::new()?;
22    // The bundled modules (reference device, function blocks, streaming):
23    let bundled = opendaq::native_library_directory().expect("native libraries");
24    builder.set_module_path(&bundled.to_string_lossy())?;
25    // Your own modules folder:
26    // builder.add_module_path("/path/to/your/modules")?;
27    let instance = Instance::from_builder(&builder)?;
28    instance.add_device("daqref://device0")?;
29
30    let channel = instance
31        .find_component("Dev/RefDev0/IO/AI/RefCh0")?
32        .expect("reference channel not found")
33        .cast::<Channel>()?;
34    channel.set_property_value("Amplitude", 5.0)?;
35    channel.set_property_value("DC", 1.0)?;
36
37    let statistics = instance
38        .add_function_block("RefFBModuleStatistics")?
39        .expect("statistics function block");
40    statistics.set_property_value("BlockSize", 100)?;
41
42    let status = statistics.status_container()?.expect("status container");
43    println!(
44        "Before connect: {} ({})",
45        status.status("ComponentStatus")?.expect("status").value()?,
46        status.status_message("ComponentStatus")?
47    );
48
49    let port = &statistics.input_ports()?[0];
50    let signal = &channel.signals()?[0];
51    port.connect(signal)?;
52
53    println!(
54        "After connect:  {} ({})",
55        status.status("ComponentStatus")?.expect("status").value()?,
56        status.status_message("ComponentStatus")?
57    );
58
59    let outputs = statistics.signals()?;
60    let avg = signal_by_local_id(&outputs, "avg")?.expect("avg signal");
61    let rms = signal_by_local_id(&outputs, "rms")?.expect("rms signal");
62    let reader = MultiReader::<f64>::new(&[avg, rms])?;
63
64    // The first reads may return nothing while the block waits for a complete
65    // input descriptor (the multi reader by default doesn't skip events), so
66    // retry until samples arrive.
67    for _attempt in 0..20 {
68        let values = reader.read(5, 1000)?;
69        if !values[0].is_empty() {
70            println!("{:>10}{:>12}", "avg", "rms");
71            for (a, r) in values[0].iter().zip(&values[1]) {
72                println!("{a:>10.4}{r:>12.4}");
73            }
74            return Ok(());
75        }
76    }
77    println!("Statistics block produced no samples in time.");
78    Ok(())
79}