Skip to main content

bobview_probe/
bobview-probe.rs

1//! Print live values of PVs through bobview's PV layer.
2//!
3//! Usage: bobview-probe [--seconds N] [--put NAME=VALUE]... NAME...
4
5use std::time::{Duration, Instant};
6
7fn main() {
8    let mut seconds = 5.0;
9    let mut puts = Vec::new();
10    let mut names = Vec::new();
11    let mut args = std::env::args().skip(1);
12    while let Some(arg) = args.next() {
13        match arg.as_str() {
14            "--seconds" => seconds = args.next().and_then(|s| s.parse().ok()).unwrap_or(seconds),
15            "--put" => puts.extend(args.next()),
16            "-h" | "--help" => {
17                println!("usage: bobview-probe [--seconds N] [--put NAME=VALUE]... NAME...");
18                return;
19            }
20            _ => names.push(arg),
21        }
22    }
23
24    let manager = pv::PvManager::new();
25    let mut pvs: Vec<_> = names
26        .iter()
27        .map(|n| (manager.subscribe(n), String::new()))
28        .collect();
29    let writers: Vec<_> = puts
30        .iter()
31        .filter_map(|p| {
32            let pair = p.split_once('=');
33            if pair.is_none() {
34                eprintln!("ignoring --put {p}: expected NAME=VALUE");
35            }
36            pair
37        })
38        .map(|(n, v)| (manager.subscribe(n), v.to_string()))
39        .collect();
40    let mut written = false;
41
42    let end = Instant::now() + Duration::from_secs_f64(seconds);
43    while Instant::now() < end {
44        if !written && writers.iter().all(|(pv, _)| pv.state().connected) {
45            for (pv, value) in &writers {
46                pv.write(value.clone());
47            }
48            written = true;
49        }
50        for (pv, last) in &mut pvs {
51            let s = pv.state();
52            let line = if let Some(e) = &s.error {
53                format!("error: {e}")
54            } else if !s.connected {
55                "disconnected".to_string()
56            } else {
57                format!("{} {:?}", s.format(None, true), s.severity)
58            };
59            if line != *last {
60                println!("{:<30} {line}", pv.name().to_string());
61                *last = line;
62            }
63        }
64        std::thread::sleep(Duration::from_millis(50));
65    }
66}