Skip to main content

streamreader_with_timestamps/
streamreader_with_timestamps.rs

1// Read samples together with their domain (time) stamps and print each
2// sample against its absolute wall-clock timestamp.
3//
4// The domain signal delivers plain integer ticks; a `TickConverter` reads the
5// domain's origin and tick resolution once and turns every tick into
6// nanoseconds since the Unix epoch.
7
8use opendaq::{Channel, Instance, StreamReader, TickConverter};
9
10/// Render nanoseconds since the Unix epoch as e.g. "2026-06-16 21:03:22.060001 UTC".
11fn timestamp_to_string(unix_nanos: i128) -> String {
12    let micros = unix_nanos.div_euclid(1_000);
13    let micro = micros.rem_euclid(1_000_000);
14    let secs = micros.div_euclid(1_000_000) as i64;
15    let (year, month, day) = civil_from_days(secs.div_euclid(86_400));
16    let s = secs.rem_euclid(86_400);
17    format!(
18        "{year:04}-{month:02}-{day:02} {:02}:{:02}:{:02}.{micro:06} UTC",
19        s / 3600,
20        s / 60 % 60,
21        s % 60
22    )
23}
24
25/// Civil date from days since 1970-01-01 (Howard Hinnant's algorithm).
26fn civil_from_days(days: i64) -> (i64, i64, i64) {
27    let z = days + 719_468;
28    let era = z.div_euclid(146_097);
29    let doe = z.rem_euclid(146_097);
30    let yoe = (doe - doe / 1460 + doe / 36_524 - doe / 146_096) / 365;
31    let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
32    let mp = (5 * doy + 2) / 153;
33    let day = doy - (153 * mp + 2) / 5 + 1;
34    let month = if mp < 10 { mp + 3 } else { mp - 9 };
35    let year = yoe + era * 400 + i64::from(month <= 2);
36    (year, month, day)
37}
38
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}