Skip to main content

DataRule

Struct DataRule 

Source
pub struct DataRule(/* private fields */);
Expand description

Rule that defines how a signal value is calculated from an implicit initialization value when the rule type is not Explicit. Data rule objects implement the Struct methods internally and are Core type ctStruct. @subsection data_rule_explicit Explicit rule When the rule type of the Data rule is set to Explicit, the values passed through the signal path, described by the Value descriptor are stored in packet buffers. The Explicit rule can have 2 optional parameters:

  • minExpectedDelta: Specifies the minimum difference in value between two subsequent samples
  • maxExpectedDelta: Specifies the maximum difference in value between two subsequent samples These are mostly used for domain signals to specify the expected rate of a signal, or the expected timeout of a signal. The delta parameters should be configured to match the deltas in terms of the raw signal values (before scaling/resolution are applied). An explicit rule must have either both or none of these parameters. To use only one, the other must be set to 0. @subsection data_rule_implicit Implicit rule When the rule type of the Data rule is not Explicit, the buffers of packets are empty. The values must instead be calculated via the Implicit value found in the packet buffers in conjunction with the parameters of the rule. Each implicit rule type specifies its own required set of parameters. @subsubsection data_rule_linear Linear rule The parameters include a delta and start integer members. The values are calculated according to the following equation: <em>packetOffset + sampleIndex * delta + start</em>. @subsubsection data_rule_linear Constant rule The parameters contain a constant number member. The value described by the constant rule is always equal to the constant. Wrapper over the openDAQ daqDataRule interface.

Implementations§

Source§

impl DataRule

Source

pub fn constant() -> Result<DataRule>

Creates a DataRule with a Constant rule type configuration.

Calls the openDAQ C function daqDataRule_createConstantDataRule().

Source

pub fn new( rule_type: DataRuleType, parameters: impl Into<Value>, ) -> Result<DataRule>

Creates a DataRule with an Explicit rule type configuration and parameters.

§Parameters
  • rule_type: .
  • parameters: .

Calls the openDAQ C function daqDataRule_createDataRule().

Source

pub fn from_builder(builder: &DataRuleBuilder) -> Result<DataRule>

Creates a DataRulePtr from Builder.

§Parameters
  • builder: DataRule Builder

Calls the openDAQ C function daqDataRule_createDataRuleFromBuilder().

Source

pub fn explicit() -> Result<DataRule>

Creates a DataRule with an Explicit rule type configuration and no parameters.

Calls the openDAQ C function daqDataRule_createExplicitDataRule().

Source

pub fn explicit_domain( min_expected_delta: impl Into<Value>, max_expected_delta: impl Into<Value>, ) -> Result<DataRule>

Creates a DataRule with an Explicit rule type configuration two optional parameters.

§Parameters
  • min_expected_delta: The lowest expected distance between two samples.
  • max_expected_delta: The highest expected distance between two samples. Most often used for domain signals to specify estimates on how close together/far apart two subsequent samples might be.

Calls the openDAQ C function daqDataRule_createExplicitDomainDataRule().

Source

pub fn linear( delta: impl Into<Value>, start: impl Into<Value>, ) -> Result<DataRule>

Creates a DataRule with a Linear rule type configuration.

§Parameters
  • delta: Coefficient by which the input data is to be multiplied.
  • start: Constant that is added to the <em>scale * value</em> multiplication result. The scale and offset are stored within the parameters member of the Rule object with the scale being at the first position of the list, and the offset at the second.

Calls the openDAQ C function daqDataRule_createLinearDataRule().

Examples found in repository?
examples/create_signal.rs (line 74)
62fn main() -> opendaq::Result<()> {
63    let instance = Instance::new()?;
64    let context = instance.context()?.expect("instance context");
65
66    let domain_descriptor = {
67        let builder = DataDescriptorBuilder::new()?;
68        builder.set_sample_type(SampleType::Int64)?;
69        builder.set_name("time")?;
70        // Origin stays at the epoch; the wall-clock time lives in the ticks.
71        builder.set_origin("1970-01-01T00:00:00Z")?;
72        builder.set_tick_resolution(TICK_RESOLUTION)?;
73        builder.set_unit(&Unit::new(-1, "s", "second", "time")?)?;
74        builder.set_rule(&DataRule::linear(TICKS_PER_SAMPLE, 0)?)?;
75        builder.build()?.expect("domain descriptor")
76    };
77    let value_descriptor = {
78        let builder = DataDescriptorBuilder::new()?;
79        builder.set_sample_type(SampleType::Float64)?;
80        builder.set_name("values")?;
81        builder.build()?.expect("value descriptor")
82    };
83
84    let domain_signal = SignalConfig::signal(&context, None, "time", None)?;
85    domain_signal.set_descriptor(&domain_descriptor)?;
86    let signal = SignalConfig::signal(&context, None, "values", None)?;
87    signal.set_descriptor(&value_descriptor)?;
88    signal.set_domain_signal(&domain_signal)?;
89
90    let reader = StreamReader::<f64, i64>::with_options(
91        &signal,
92        StreamReaderOptions {
93            timeout_type: ReadTimeoutType::Any,
94            ..Default::default()
95        },
96    )?;
97
98    // Stream a few seconds of a 5 Hz signal in real time.  Each one-second
99    // batch is one packet of 5 samples; the ticks stay contiguous across
100    // batches (batch k starts at start_tick + k*1000 ms), so the whole run is
101    // an unbroken 5 Hz stream anchored to when the program started.
102    let batches = 3;
103    let start_tick = now_ticks();
104    let to_timestamp = TickConverter::from_signal(&signal)?;
105    println!(
106        "Streaming {SAMPLES_PER_SECOND} samples/second, starting at {}",
107        time_of_day(to_timestamp.tick_to_unix_nanos(start_tick))
108    );
109    for batch in 0..batches {
110        let base_sample = batch * SAMPLES_PER_SECOND;
111        let offset = start_tick + base_sample as i64 * TICKS_PER_SAMPLE;
112        let samples: Vec<f64> = (0..SAMPLES_PER_SECOND)
113            .map(|i| (2.0 * PI * ((base_sample + i) as f64 / 25.0)).sin())
114            .collect();
115        send_chunk(
116            &signal,
117            &domain_descriptor,
118            &value_descriptor,
119            offset,
120            &samples,
121        )?;
122
123        let (values, ticks) = reader.read_with_domain(100, 1000)?;
124        for (value, tick) in values.iter().zip(&ticks) {
125            println!(
126                "  {}  ->  {value:.4}",
127                time_of_day(to_timestamp.tick_to_unix_nanos(*tick))
128            );
129        }
130        std::thread::sleep(Duration::from_secs(1));
131    }
132    Ok(())
133}
Source

pub fn parameters(&self) -> Result<HashMap<String, Value>>

Gets a dictionary of string-object key-value pairs representing the parameters used to evaluate the rule.

§Returns
  • parameters: The dictionary containing the rule parameter members.

Calls the openDAQ C function daqDataRule_getParameters().

Source

pub fn type_(&self) -> Result<DataRuleType>

Gets the type of the data rule.

§Returns
  • type: The type of the data rule.

Calls the openDAQ C function daqDataRule_getType().

Methods from Deref<Target = BaseObject>§

Source

pub fn cast<T: Interface>(&self) -> Result<T>

Query this object for interface T, returning a wrapper that owns its own reference.

This is a genuine queryInterface: an object’s interfaces live at different virtual-table offsets, so the pointer for one interface is not binary-compatible with another and must be queried, not merely reinterpreted. Fails with an openDAQ error when the object does not implement T (use BaseObject::try_cast / BaseObject::is_a to probe first).

For the few interfaces the C API exposes no GUID for (T::interface_id() is None), the pointer is reinterpreted unchecked, which is sound only when the object really lies on T’s inheritance chain.

Examples found in repository?
examples/call_function_property.rs (line 14)
10fn function_property(device: &Device, name: &str) -> opendaq::Result<FunctionObject> {
11    device
12        .property_value(name)?
13        .into_object()?
14        .cast::<FunctionObject>()
15}
More examples
Hide additional examples
examples/component_tree.rs (line 48)
46fn children(component: &Component) -> opendaq::Result<Vec<Component>> {
47    if component.is_a::<Folder>() {
48        component.cast::<Folder>()?.items()
49    } else {
50        Ok(Vec::new())
51    }
52}
examples/multireader.rs (line 24)
20fn find_channel(instance: &Instance, path: &str) -> opendaq::Result<Channel> {
21    instance
22        .find_component(path)?
23        .unwrap_or_else(|| panic!("channel {path} not found"))
24        .cast::<Channel>()
25}
examples/search_filter.rs (line 25)
22fn show<T: Interface>(label: &str, components: Vec<T>) -> opendaq::Result<()> {
23    let ids = components
24        .iter()
25        .map(|c| c.to_base_object().cast::<Component>()?.local_id())
26        .collect::<opendaq::Result<Vec<_>>>()?;
27    let listing = if ids.is_empty() {
28        "(none)".to_string()
29    } else {
30        ids.join(", ")
31    };
32    println!("{label}\n    => {listing}\n");
33    Ok(())
34}
35
36fn main() -> opendaq::Result<()> {
37    let instance = Instance::new()?;
38    instance.add_device("daqref://device0")?;
39    let root = instance.root_device()?.expect("root device");
40
41    // Give a couple of channels some tags, so the tag filter has something to
42    // match.  (RefCh0 and RefCh1 come from the reference device unlabelled.)
43    let everything = SearchFilter::recursive(&SearchFilter::any()?)?;
44    for channel in root.channels_with(Some(&everything))? {
45        let tags = channel.tags()?.expect("tags").cast::<TagsPrivate>()?;
46        tags.add("analog")?;
47        if channel.local_id()? == "RefCh0" {
48            tags.add("primary")?;
49        }
50    }
51
52    show(
53        "channels, no filter (immediate children only)",
54        root.channels()?,
55    )?;
56
57    show(
58        "channels, recursive(any)",
59        root.channels_with(Some(&SearchFilter::recursive(&SearchFilter::any()?)?))?,
60    )?;
61
62    show(
63        "channels, recursive(id = RefCh1)",
64        root.channels_with(Some(&SearchFilter::recursive(&SearchFilter::local_id(
65            "RefCh1",
66        )?)?))?,
67    )?;
68
69    let ai0_or_ai1 = SearchFilter::or(
70        &SearchFilter::local_id("AI0")?,
71        &SearchFilter::local_id("AI1")?,
72    )?;
73    show(
74        "signals, recursive(id = AI0 OR id = AI1)",
75        root.signals_with(Some(&SearchFilter::recursive(&ai0_or_ai1)?))?,
76    )?;
77
78    let not_ref_ch1 = SearchFilter::not(&SearchFilter::local_id("RefCh1")?)?;
79    show(
80        "channels, recursive(NOT id = RefCh1)",
81        root.channels_with(Some(&SearchFilter::recursive(&not_ref_ch1)?))?,
82    )?;
83
84    let analog_and_not_ref_ch1 = SearchFilter::and(
85        &SearchFilter::required_tags(vec!["analog"])?,
86        &SearchFilter::not(&SearchFilter::local_id("RefCh1")?)?,
87    )?;
88    show(
89        "channels, recursive(tag = analog AND NOT id = RefCh1)",
90        root.channels_with(Some(&SearchFilter::recursive(&analog_and_not_ref_ch1)?))?,
91    )?;
92
93    Ok(())
94}
examples/streamreader.rs (line 15)
8fn main() -> opendaq::Result<()> {
9    let instance = Instance::new()?;
10    instance.add_device("daqref://device0")?;
11
12    let channel = instance
13        .find_component("Dev/RefDev0/IO/AI/RefCh0")?
14        .expect("reference channel not found")
15        .cast::<Channel>()?;
16    let signal = &channel.signals()?[0];
17
18    let reader = StreamReader::<f64>::new(signal)?;
19    println!("some samples: {:?}", reader.read(100, 1000)?.values());
20    println!("and more samples: {:?}", reader.read(100, 1000)?.values());
21    println!("and more still: {:?}", reader.read(100, 1000)?.values());
22    Ok(())
23}
examples/streamreader_with_timestamps.rs (line 46)
39fn main() -> opendaq::Result<()> {
40    let instance = Instance::new()?;
41    instance.add_device("daqref://device0")?;
42
43    let channel = instance
44        .find_component("Dev/RefDev0/IO/AI/RefCh0")?
45        .expect("reference channel not found")
46        .cast::<Channel>()?;
47    let signal = &channel.signals()?[0];
48
49    let reader = StreamReader::<f64>::new(signal)?;
50    let converter = TickConverter::from_signal(signal)?;
51
52    let (values, ticks) = reader.read_with_domain(10, 2000)?;
53    println!("Read {} samples:", values.sample_count());
54    for (value, tick) in values.iter().zip(&ticks) {
55        println!(
56            "  {value:.6} @ {}",
57            timestamp_to_string(converter.tick_to_unix_nanos(*tick))
58        );
59    }
60    Ok(())
61}
Source

pub fn try_cast<T: Interface>(&self) -> Option<T>

Like BaseObject::cast, but returns None when the object does not implement T.

Source

pub fn is_a<T: Interface>(&self) -> bool

True when the object implements interface T (a borrowInterface probe; adds no reference). Returns false for interfaces without a GUID in the C API, which cannot be probed.

Examples found in repository?
examples/component_tree.rs (line 47)
46fn children(component: &Component) -> opendaq::Result<Vec<Component>> {
47    if component.is_a::<Folder>() {
48        component.cast::<Folder>()?.items()
49    } else {
50        Ok(Vec::new())
51    }
52}
Source

pub fn hash_code(&self) -> Result<usize>

The object’s hash code.

Source

pub fn equals<T: Interface>(&self, other: &T) -> Result<bool>

True when openDAQ considers the two objects equal.

Source

pub fn ptr_eq<T: Interface>(&self, other: &T) -> bool

Identity comparison: both wrappers refer to the same native object. (Note that pointers to different interfaces of one object differ; this compares the raw interface pointers.)

Source

pub fn dispose(&self) -> Result<()>

Release the object’s internal resources early (openDAQ dispose). The wrapper itself stays alive; most callers never need this.

Source

pub fn component_kind(&self) -> Option<ComponentKind>

The most-derived component interface this object implements (probed most-derived first), or None when it is not a component.

Examples found in repository?
examples/component_tree.rs (line 10)
8fn type_label(component: &Component) -> String {
9    component
10        .component_kind()
11        .map_or_else(|| "Component".to_string(), |kind| format!("{kind:?}"))
12}
Source

pub fn to_value(&self) -> Result<Value>

The natural Rust value of this object: a boxed scalar yields its native value, a daq list a Vec, a daq dict key/value pairs – with elements converted recursively – and an object with no natural Rust form (a device, a property object, …) comes back as Value::Object, for the caller to BaseObject::cast.

Trait Implementations§

Source§

impl Clone for DataRule

Source§

fn clone(&self) -> DataRule

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DataRule

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Deref for DataRule

Source§

type Target = BaseObject

The resulting type after dereferencing.
Source§

fn deref(&self) -> &BaseObject

Dereferences the value.
Source§

impl Display for DataRule

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<&DataRule> for Value

Source§

fn from(value: &DataRule) -> Value

Converts to this type from the input type.
Source§

impl From<DataRule> for Value

Source§

fn from(value: DataRule) -> Value

Converts to this type from the input type.
Source§

impl Interface for DataRule

Source§

const NAME: &'static str = "daqDataRule"

The openDAQ interface name, e.g. "daqDevice".
Source§

fn interface_id() -> Option<IntfID>

The interface’s GUID, or None for the few coretypes interfaces the C API exposes no id for (IBaseObject, IFunction, IProcedure, …).
Source§

unsafe fn from_raw(ptr: *mut c_void) -> Option<Self>

Adopt an owned raw interface pointer (takes ownership of one reference; does not add one). Returns None for null. Read more
Source§

fn as_base_object(&self) -> &BaseObject

This wrapper viewed as the root IBaseObject interface.
Source§

fn as_raw(&self) -> *mut c_void

The raw interface pointer (still owned by this wrapper).
Source§

fn to_base_object(&self) -> BaseObject

A new owning BaseObject handle to the same underlying object.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.